最近要在系统弹出的数字键盘上的左下角额外添加一个自定制的完成按钮,于是研究了一下系统自带键盘添加自定制按钮的实现方式。总结了一下大体上的通用做法,原理大概是这样:当页面上的文本框或其他输入源因为用户的点击而变成第一响应者的时候(becomeFirstResponder),系统键盘就会弹出。而每次键盘弹出或收起时,都会向系统发送相关的键盘事件即通知消息(notification)。所以,我们只要在键盘弹出或收起时捕获相关的键盘事件,并且在键盘对应的window上的相应位置添加或移除我们自定制的按钮即可。
按照这种思路,在键盘弹出时添加上我们自定制的按钮是完全可行的。但是,如果只是这样简单的处理,造成的效果是:键盘弹出和自定制按钮的添加是不同步的。有时候键盘还没有弹出自定制的按钮就已经加在试图上了,有时候键盘弹出后自定制的按钮才添加上去。那么我们如何使得键盘的弹出和自定制按钮的添加能同步进行呢,要完成这种平滑的过度弹出效果,还需要获得键盘弹出的动画时间和动画类型,然后让自定制按钮的添加动画和键盘的弹出、收起动作同步。
1、首先在 viewWillAppear 方法中注册监听相应的键盘通知,并且要在 viewWillDisappear 方法中注销通知
- (void)viewWillAppear:(BOOL)animated { //注册键盘显示通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardDidShow:) name:UIKeyboardWillShowNotification object:nil]; //注册键盘隐藏通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; [super viewWillAppear:animated]; }
-(void)viewWillDisappear:(BOOL)animated{ //注销键盘显示通知 [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; [super viewWillDisappear:animated]; }
2、处理键盘弹出和收起事件
// 键盘出现处理事件 - (void)handleKeyboardDidShow:(NSNotification *)notification { // NSNotification中的 userInfo字典中包含键盘的位置和大小等信息 NSDictionary *userInfo = [notification userInfo]; // UIKeyboardAnimationDurationUserInfoKey 对应键盘弹出的动画时间 CGFloat animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]; // UIKeyboardAnimationCurveUserInfoKey 对应键盘弹出的动画类型 NSInteger animationCurve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue]; //数字彩,数字键盘添加“完成”按钮 if (doneInKeyboardButton){ [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:animationDuration];//设置添加按钮的动画时间 [UIView setAnimationCurve:(UIViewAnimationCurve)animationCurve];//设置添加按钮的动画类型 //设置自定制按钮的添加位置(这里为数字键盘添加“完成”按钮) doneInKeyboardButton.transform=CGAffineTransformTranslate(doneInKeyboardButton.transform, 0, -53); [UIView commitAnimations]; } }
// 键盘消失处理事件 - (void)handleKeyboardWillHide:(NSNotification *)notification { // NSNotification中的 userInfo字典中包含键盘的位置和大小等信息 NSDictionary *userInfo = [notification userInfo]; // UIKeyboardAnimationDurationUserInfoKey 对应键盘收起的动画时间 CGFloat animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]; if (doneInKeyboardButton.superview) { [UIView animateWithDuration:animationDuration animations:^{ //动画内容,将自定制按钮移回初始位置 doneInKeyboardButton.transform=CGAffineTransformIdentity; } completion:^(BOOL finished) { //动画结束后移除自定制的按钮 [doneInKeyboardButton removeFromSuperview]; }]; } }
3、点击输入框,初始化自定制按钮并弹出键盘
//点击输入框 - (IBAction)editingDidBegin:(id)sender{ //初始化数字键盘的“完成”按钮 [self configDoneInKeyBoardButton]; }
//初始化,数字键盘“完成”按钮 - (void)configDoneInKeyBoardButton{ CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; //初始化 if (doneInKeyboardButton == nil) { doneInKeyboardButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain]; [doneInKeyboardButton setTitle:@"完成" forState:UIControlStateNormal]; [doneInKeyboardButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; doneInKeyboardButton.frame = CGRectMake(0, screenHeight, 106, 53); doneInKeyboardButton.adjustsImageWhenHighlighted = NO; [doneInKeyboardButton addTarget:self action:@selector(finishAction) forControlEvents:UIControlEventTouchUpInside]; } //每次必须从新设定“完成”按钮的初始化坐标位置 doneInKeyboardButton.frame = CGRectMake(0, screenHeight, 106, 53); //由于ios8下,键盘所在的window视图还没有初始化完成,调用在下一次 runloop 下获得键盘所在的window视图 [self performSelector:@selector(addDoneButton) withObject:nil afterDelay:0.0f]; } - (void) addDoneButton{ //获得键盘所在的window视图 UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1]; [tempWindow addSubview:doneInKeyboardButton]; // 注意这里直接加到window上 }
//点击“完成”按钮事件,收起键盘 -(void)finishAction{ [[[UIApplication sharedApplication] keyWindow] endEditing:YES];//关闭键盘 }
按照这种思路和实现原理,可以在键盘上方等地方添加输入框等其他自定制控件并且可以跟随键盘的弹出和收起平滑过度出现。
时间: 2024-10-01 04:44:02