在iOS开发中,隐藏键盘是个基本功,很久之前就想做下笔记了,一直拖到现在。下面是我私人总结的一些办法,不过和网上许多文章也是大同小异,在为自己做笔记的同时也给一些初学者一些启示。
这个方法我用得比较多,可以在IB中添加,也可以用代码创建。
(1)在IB中添加Tap Gesture Recognizer
然后将tap手势识别器和View Controller中的一个IBAction连接,代码如下:
- (IBAction)hideKeyboard:(id)sender { NSLog(@"Tap in view"); [self hideKeyboardInView:self.view]; }
// 方法一: [self.firstTextField resignFirstResponder]; [self.secondTextField resignFirstResponder]; [self.FirstTextView resignFirstResponder]; [self.SecondTextView resignFirstResponder];
二是递归遍历视图目录,判断是否text field和text view组件,如果是就resign:
// 方法二: for (UIView *view in aView.subviews) { if ([view.subviews count] > 0) { [self hideKeyboardInView:view]; } if ([view isKindOfClass:[UITextView class]] || [view isKindOfClass:[UITextField class]]) { [view resignFirstResponder]; } }
个人觉得,如果文本编辑组件不是很多的话就用第一种做法,因为如果视图上的子视图很多的话,使用第二种做法递归遍历视图目录的过程其耗费较大。
(2)代码创建Tap Gesture Recognizer
UITapGestureRecognizer *tapInView = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboardInView:)]; [self.view addGestureRecognizer:tapInView];
说明:
或许你担心tap手势对于整个视图有效,在tap文本编辑视图时,会不会发送冲突呢?以上代码在hideKeyboard:那个IBAction方法中设置了一句NSLog(@"Tap in view"); 现在尝试运行程序并轻击text field和text view等,结果控制台无输出,而轻击视图时就会输出Tap in view,因此二者无冲突,可以放心使用。
另外,如果只是单纯的让self.view becomeFirstResponder,而没有让所有文本编辑组件resign,那么键盘也不会隐藏,所以不要偷懒了。
这个方法我用得比较少,因为之前用的组件中很少涉及到UITextField,一般都是针对UITextView做隐藏键盘处理。
在该方法中,我们在UITextFieldDelegate中的一个方法中设置resignFirstResponder就可以了。
必须声明遵循的协议:
@interface SecondViewController () <UITextFieldDelegate>
#pragma mark - UITextField Delegate - (void)textFieldDidBeginEditing:(UITextField *)textField { NSLog(@"Did Begin Editing"); } - (void)textFieldDidEndEditing:(UITextField *)textField { // [textField resignFirstResponder]; NSLog(@"Did End Editing"); NSLog(@"%@", textField.text); } - (BOOL)textFieldShouldReturn:(UITextField *)textField { if (textField.returnKeyType == UIReturnKeyDone) { NSLog(@"Hide Keyboard"); [textField resignFirstResponder]; } return YES; }
self.textField.delegate = self;
注意代码中我规定了只有键盘返回的Key为Done时(UITextField中没有换行,这个可以放心)才会隐藏键盘,所以还要设置UITextField的返回类型:(一般这个过程是不需要的,只是我的强迫症发作了)
只有键盘隐藏了才算编辑完成,DidEndEditing方法才会被调用:
2014-02-15 23:44:46.448 HideKeyboardDemo[4371:70b] Did Begin Editing 2014-02-15 23:44:48.525 HideKeyboardDemo[4371:70b] Hide Keyboard 2014-02-15 23:44:48.527 HideKeyboardDemo[4371:70b] Did End Editing
这种方法的好处是可以对所有委托为自己的UITextField组件有效。不足是对UITextView组件无效,而UITextViewDelegate中也没有shouldReturn的方法,虽然网上有文章是使用shouldChangeTextInRange:方法隐藏键盘,但是这样会覆盖掉TextView的换行功能,所以个人并不赞成用return键隐藏键盘。
这个在我之前的一篇关于iOS 7 TextKit中的文章已经介绍过,这个是iOS 7的新特性,很不错,但是也有其不足。
使用非常简单:
self.FirstTextView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; self.SecondTextView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
如果是UIScrollViewKeyboardDismissModeInteractive,这个用文字表述有点吃力,其实就是先滚动下UITextView,然后手指贴着屏幕向下划,一直带动键盘退出屏幕,这个时候键盘看起来就像是具备交互性的一样,Interactive由此而来。例如:
优点:方便。
缺点:一,对UITextField无效。二,如果UITextView中的内容较少,无法超过UITextView的范围,也就是不会出现UIScrollView的滚动效果,那么上面的手势都会失效,这样我们又被迫回到方法一写个手势识别器了。例如:
连scroll的效果都出不来,更加谈不上dismiss keyboard了,这是其最大的不足,希望Apple会改进。
方法四其实说不上是一个方法,就是iPad中的键盘不用我们费心而已,UITextView和UITextField通用:
当然关于隐藏键盘还有很多解决方案,例如有人在touchesBegan方法中调用resignFirstResponder方法,个人并不赞成这种做法,因为在一些画图或有特定手势的程序中touchesBegan等方法有着特定的用途,无故加入个resignFirstResponder方法一来可能执行了不必要的代码,二来影响代码的美观性。有时候我们也可以在视图中直接加一个按钮,然后在里面调用resign方法就可以了。所以隐藏键盘的方案很多,本文的方法只是其中几个。
感觉iOS的API中隐藏键盘方面做得还是不够好,相信Apple以后会推出更加简洁的方法,甚至iPhone上面推出一个像iPad键盘那样的让键盘消失的键,耐心等吧。这段笔记先做到这里了。
最后根据国际惯例,上传了Demo,有兴趣的可以下载看看:点此进入下载页面
2014/7/24
假设你的View中有一大堆UITextField,UITextView,此时必不可少的就是写一个让键盘消失的方法,现在为大家介绍一个超级暴力的逆天方法。看看定义在UITextField中关于UIView的一个category:
@interface UIView (UITextField) - (BOOL)endEditing:(BOOL)force; // use to make the view or any subview that is the first responder resign (optionally force) @end
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UITextField *textField1; @property (weak, nonatomic) IBOutlet UITextField *textField2; @property (weak, nonatomic) IBOutlet UITextField *textField3; @property (weak, nonatomic) IBOutlet UITextView *textView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(endEditing:)]; swipeGesture.direction = UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp; [self.view addGestureRecognizer:swipeGesture]; } - (void)endEditing:(id)sender { [self.view endEditing:YES]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end
本方法适用于视图中有一大堆输入控件的情况,此时可以节省大量的代码。
注意:该方法在iOS 2.0以后就可以用了,放心使用吧。具体的副作用暂时还不清楚,可能消耗的系统资源会比较多吧,而且如果传入的force参数为YES,某些UI组件正在执行的动作可能会被强行打断,感觉该方法不能滥用。
参考资料:
http://objdev.com/2013/11/Dismissing-iOS-Keyboard-Self-View-EndEditing