多个UITextField的处理(实现键盘排版)

第一种方法(没有禁止“上、下一个的按钮”)

Main.storyboard一定要设置相应的控制器类

KeyboardToolbar.h

#import <UIKit/UIKit.h>

@class KeyboardToolbar;

typedef enum {

    BTNTypePrevious = 0,

    BTNTypeNext,

    BTNTypeDone,

}BTNType;

 

@protocol KeyboardToolbarDelegate <NSObject>

 

-(void)keyboardTool:(KeyboardToolbar *)toolbar btnClickType:(BTNType)btnType;

@end

 

@interface KeyboardToolbar : UIToolbar

 

+(instancetype)toolbar;

 

@property(nonatomic,weak)id<KeyboardToolbarDelegate> kbtDelegate;

 

@end

#import "KeyboardToolbar.h"

 

@interface KeyboardToolbar()

 

- (IBAction)btnClick:(UIBarButtonItem *)item;

 

 

@end

 

@implementation KeyboardToolbar

 

+(instancetype)toolbar{

    return [[[NSBundle mainBundle] loadNibNamed:@"KeyboardToolbar" owner:nil options:nil] lastObject];

}

 

- (IBAction)btnClick:(UIBarButtonItem *)item {

    

    BTNType btnType = BTNTypeDone;//默认是Done

    

    if ([self.kbtDelegate respondsToSelector:@selector(keyboardTool:btnClickType:)]) {

        if (item.tag == 0) {

            btnType = BTNTypePrevious;

        }else if(item.tag == 1){

            btnType = BTNTypeNext;

        }

        

        [self.kbtDelegate keyboardTool:self btnClickType:btnType];

    }

}

@end

KeyboardToolbar.xib

 

xib中一定要设置与控制器类相对应的类

ViewController.m

//

//  ViewController.m

//  08.注册【排版技巧】

//

//  Created by Yong Feng Guo on 14-12-22.

//  Copyright (c) 2014 Fung. All rights reserved.

//

 

#import "ViewController.h"

#import "KeyboardToolbar.h"

 

@interface ViewController ()<KeyboardToolbarDelegate,UITextFieldDelegate>

@property (weak, nonatomic) IBOutlet UIView *registerContainer;

@property(nonatomic,strong)KeyboardToolbar *toolbar;//键盘的工具条

@property(nonatomic,strong)NSArray *fields;//注册框容器所有输入框

 

@end

 

@implementation ViewController

 

/**

 *获取注册框容器的所有输入框

 *遍历所有UITextField

 *UITextField添加工具栏

 */

-(NSArray *)fields{

    if (!_fields) {

        NSArray *subviews = self.registerContainer.subviews;

        NSMutableArray *fieldsM = [NSMutableArray array];

        NSLog(@"%ld",subviews.count);

        //遍历所有UITextField添加到数组中

        for (id obj in subviews) {

            if ([obj isKindOfClass:[UITextField class]]) {

                //添加工具条

                UITextField *tf = obj;

                tf.inputAccessoryView = self.toolbar;

                [fieldsM addObject:tf];

            }

        }

        _fields = fieldsM;

    }

    

    return _fields;

}

 

/**

 * 键盘工具条

 */

-(KeyboardToolbar *)toolbar{

    if (!_toolbar) {

        _toolbar = [KeyboardToolbar toolbar];

        _toolbar.kbtDelegate = self;

    }

    return _toolbar;

}

 

- (void)viewDidLoad {

    [super viewDidLoad];

//#warning 遍历后数组为空,去除size classes

    [self fields];

   

    //监听键盘的显示

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kbWillShow:) name:UIKeyboardWillShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kbWillHide:) name:UIKeyboardWillHideNotification object:nil];

}

 

-(void)kbWillHide:(NSNotification *)noti{

    [UIView animateWithDuration:0.25 animations:^{

        self.view.transform = CGAffineTransformIdentity;

    }];

}

-(void)kbWillShow:(NSNotification *)noti{

    NSLog(@"%@",noti.userInfo);

    //键盘高度

    CGFloat kbY = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y;

    

    //响应者的最大Y

    UITextField *firstResp = [self firstResp];

    //响应者在控制器view的最高的Y

    CGFloat tfMaxYInView = CGRectGetMaxY(firstResp.frame) + self.registerContainer.frame.origin.y;

    

    CGFloat delta = kbY - tfMaxYInView;

    NSLog(@"%f",delta);

    if (delta < 0) {

        [UIView animateWithDuration:0.25 animations:^{

                self.view.transform = CGAffineTransformMakeTranslation(0, delta);

        }];

 

    }

 

}

 

-(void)dealloc{

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

 

-(void)keyboardTool:(KeyboardToolbar *)toolbar btnClickType:(BTNType)btnType{

    // 获取当前响应者

    UITextField *firstResp = [self firstResp];

    

    // 如果没有当前响应者,直接返回

    if(!firstResp) return;

    

    //获取响应者索

    NSInteger indexOfFirstResp = [self.fields indexOfObject:firstResp];

    

    // 更改响应者

    if (btnType == BTNTypePrevious && indexOfFirstResp != 0){//上一个

        [firstResp resignFirstResponder];

 

        [self.fields[indexOfFirstResp - 1] becomeFirstResponder];

    }else if(btnType == BTNTypeNext && indexOfFirstResp != self.fields.count -1) {//下一个

        [firstResp resignFirstResponder];

        [self.fields[indexOfFirstResp + 1] becomeFirstResponder];

    }else if(btnType == BTNTypeDone){

        [self.view endEditing:YES];

    }

}

 

/**

 * 返回第一响应者

 */

-(UITextField *)firstResp{

    for (id obj in self.fields) {

        if ([obj isFirstResponder]) {

            return obj;

            break;

        }

    }

    return nil;

}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    [self.view endEditing:YES];

}

 

 

 

@end

第二种方式(上、下一个按钮可以禁止,推荐使用)

Main.storyboard与上面一样

KeyboardToolbar.h

#import <UIKit/UIKit.h>

@class KeyboardToolbar;

typedef enum {

    BTNTypePrevious = 0,

    BTNTypeNext,

    BTNTypeDone,

}BTNType;

 

@protocol KeyboardToolbarDelegate <NSObject>

 

-(void)keyboardTool:(KeyboardToolbar *)toolbar btndidSelected:(UIBarButtonItem *)item;

@end

 

@interface KeyboardToolbar : UIToolbar

//上一个按钮

@property (weak, nonatomic) IBOutlet UIBarButtonItem *previousItem;

//下一个按钮

@property (weak, nonatomic) IBOutlet UIBarButtonItem *nextItem;

 

+(instancetype)toolbar;

 

@property(nonatomic,weak)id<KeyboardToolbarDelegate> kbtDelegate;

 

@end

KeyboardToolbar.m

#import "KeyboardToolbar.h"

 

@interface KeyboardToolbar()

 

- (IBAction)btnClick:(UIBarButtonItem *)item;

 

 

@end

 

@implementation KeyboardToolbar

 

+(instancetype)toolbar{

    return [[[NSBundle mainBundle] loadNibNamed:@"KeyboardToolbar" owner:nil options:nil] lastObject];

}

 

- (IBAction)btnClick:(UIBarButtonItem *)item {

    

    BTNType btnType = BTNTypeDone;//默认是Done

    

    if ([self.kbtDelegate respondsToSelector:@selector(keyboardTool:btndidSelected:)]) {

        if (item.tag == 0) {

            btnType = BTNTypePrevious;

        }else if(item.tag == 1){

            btnType = BTNTypeNext;

        }

        

        [self.kbtDelegate keyboardTool:self btndidSelected:item];

    }

}

@end

KeyboardToolbar.xib与上面一样

ViewController.m

//

//  ViewController.m

//  多个UITextField的处理

//

//  Created by huan on 16/1/20.

//  Copyright © 2016 huanxi. All rights reserved.

//

 

#import "ViewController.h"

#import "KeyboardToolbar.h"

@interface ViewController ()<KeyboardToolbarDelegate, UITextFieldDelegate>

@property (weak, nonatomic) IBOutlet UIView *registerContainer;

//@property (weak, nonatomic) UIBarButtonItem *currentItem;//当前的Item

@property (nonatomic, strong) KeyboardToolbar *toolbar;//键盘的工具条

@property (nonatomic, strong) NSArray *fields;//将所有的输入框放入一个数组里

 

@end

 

@implementation ViewController

/**

 * 懒加载toolbar

 *

 */

-(KeyboardToolbar *)toolbar{

    if (!_toolbar) {

        _toolbar = [KeyboardToolbar toolbar];

        _toolbar.kbtDelegate = self;

    }

    return _toolbar;

}

 

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    //定义一个可变数组

    NSMutableArray *fieldsM = [NSMutableArray array];

    //warning sizeClasses 导航注册框窗口的子控制器为空,去掉storyboardsizeClasses

    //遍历UITextField 添加键盘工具条

    NSLog(@"%@", self.registerContainer.subviews);

    for (UIView *subView in self.registerContainer.subviews) {

        if ([subView isKindOfClass:[UITextField class]]) {

            UITextField *tf = (UITextField *)subView;

            tf.inputAccessoryView = self.toolbar;

            //绑定tag

            tf.tag = fieldsM.count;

            [fieldsM addObject:tf];

        }

    }

    self.fields = fieldsM;

    //监听键盘事件

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willShow:) name:UIKeyboardWillShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willHide:) name:UIKeyboardWillHideNotification object:nil];

}

//显示键盘

-(void)willShow:(NSNotification *)notifi{

    NSLog(@"%@", notifi.userInfo);

    //当键盘挡住UITextField,TextField所在父控件往上移

    //1.获得当前选中的UITextField的最大Y

    //当前获取焦点的textfield

    UITextField *curretTf = self.fields[[self indexOfFirstResponder]];

    //键盘一弹出,就判断上一个,下一个按钮可不可用

    if(curretTf.tag == 0){

        self.toolbar.previousItem.enabled = NO;

    }

    if (curretTf.tag == self.fields.count - 1) {

        self.toolbar.nextItem.enabled = NO;

    }

//    curretTf.frame.origin.y + curretTf.frame.size.height

    CGFloat maxY = CGRectGetMaxY(curretTf.frame) + self.registerContainer.frame.origin.y;

    //2.获得键盘的y

    CGRect kbEndFrm = [notifi.userInfo[UIKeyboardFrameEndUserInfoKey]CGRectValue];

    CGFloat kbY = kbEndFrm.origin.y;

    //3.进行比较

    //计算距离

    CGFloat delta = kbY - maxY;

    if (delta < 0) {//需要往上移

        //添加动画

        [UIView animateWithDuration:0.25 animations:^{//动画是防止卡而设置的视觉效果

            self.view.transform = CGAffineTransformMakeTranslation(0, delta); //view的属性:形变

        }];

        

    }

    

}

//隐藏键盘

-(void)willHide:(NSNotification *)notifi{

    [UIView animateWithDuration:0.25 animations:^{

       self.view.transform = CGAffineTransformIdentity;//恢复原状,如果没这句话,会有黑色的覆盖下面,因为没有隐藏键盘

    }];

    

    //还原工具条的item为可用

    self.toolbar.previousItem.enabled = YES;//又隐藏又显示会造成两个按钮禁止。所以写了这两句代码。

    self.toolbar.nextItem.enabled = YES;

}

 

/**

 * 获取当前的响应者的索引

 */

-(NSInteger)indexOfFirstResponder{

    for (UITextField *tf in self.fields) {

        if (tf.isFirstResponder) {

            return tf.tag;

        }

    }

    //返回-1当前响应者

    return -1;

}

 

-(void)keyboardTool:(KeyboardToolbar *)toolbar btndidSelected:(UIBarButtonItem *)item{

//    self.currentItem = item;

    switch (item.tag) {

        case 0://上一个

            [self previous];

            break;

        case 1://下一个

            [self next];

//            NSLog(@"%ld")

            break;

        case 2://完成 键盘消失

            [self.view endEditing:YES];

            break;

            

        default:

            break;

    }

}

 

-(void)previous{

    //获取当前的焦点

    NSInteger currentIndex = [self indexOfFirstResponder];

    NSLog(@"%ld", currentIndex);

    self.toolbar.nextItem.enabled = YES;

//    if (currentIndex == 1) {

//        //禁止上一个按钮(“上一个变白 就是禁用)

////        self.currentItem.enabled = NO;

//        self.toolbar.previousItem.enabled = NO;

//    }

    //获得上一个索引

    NSInteger previousIndex = currentIndex - 1;

    

    //不当响应者

//    [self.fields[currentIndex] resignFirstResponder];//把之前的焦点去掉。在iOS9没影响

 

    //索引大于0

    if (previousIndex >= 0) {

        [self.fields[previousIndex] becomeFirstResponder];

    }

    

//    //如果没有焦点,或者当前是第一个UITextField为响应者,不应该点 上一下

//    if (currentIndex == -1 || currentIndex == 0) {

////        self.

//        return;

    

}

 

-(void)next{

    //获取当前的焦点

    NSInteger currentIndex = [self indexOfFirstResponder];

    NSLog(@"%ld", currentIndex);

    

    self.toolbar.previousItem.enabled = YES;

//    //判断当前索引等于什么时候,下个按钮不可以用

//    if(currentIndex == self.fields.count - 2){

//        self.toolbar.nextItem.enabled = NO;

//    }

    

    //不当响应者

//    [self.fields[currentIndex] resignFirstResponder];

 

    //设置下一个焦点

    if(currentIndex != -1 && currentIndex != self.fields.count - 1){

        NSInteger nextIndex = currentIndex + 1;

        [self.fields[nextIndex] becomeFirstResponder];

    }

}

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

//点击空白处键盘消失

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    [self.view endEditing:YES];

}

 

 

 

@end

这种方式解决了上下按钮禁止问题、不移动问题、两个按钮同时禁止问题(在键盘隐藏里),增加动画效果,有视觉上的美感。

 

原文地址:https://www.cnblogs.com/Lu2015-10-03/p/5147771.html