多个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 导航注册框窗口的子控制器为空,去掉storyboard的sizeClasses
//遍历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
这种方式解决了上下按钮禁止问题、不移动问题、两个按钮同时禁止问题(在键盘隐藏里),增加动画效果,有视觉上的美感。