iOS 隐藏键盘

来源:互联网 发布:2008数据库重建日志 编辑:程序博客网 时间:2024/05/18 01:15

在iOS开发中,隐藏键盘是个基本功,很久之前就想做下笔记了,一直拖到现在。下面是我私人总结的一些办法,不过和网上许多文章也是大同小异,在为自己做笔记的同时也给一些初学者一些启示。


方法一:在视图中添加Tap手势识别器

这个方法我用得比较多,可以在IB中添加,也可以用代码创建。

(1)在IB中添加Tap Gesture Recognizer


然后将tap手势识别器和View Controller中的一个IBAction连接,代码如下:

- (IBAction)hideKeyboard:(id)sender {    NSLog(@"Tap in view");    [self hideKeyboardInView:self.view];}

在hideKeyboardInView:方法中有两种做法,一是手动resign所有的text field和text 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,那么键盘也不会隐藏,所以不要偷懒了。



方法二:使用UITextFieldDelegate

这个方法我用得比较少,因为之前用的组件中很少涉及到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;}

还要设置好UITextField的委托,可以代码设置:

self.textField.delegate = self;

也可以在IB中设置(注意连接的是View Controller,而不是其View):



注意代码中我规定了只有键盘返回的Key为Done时(UITextField中没有换行,这个可以放心)才会隐藏键盘,所以还要设置UITextField的返回类型:(一般这个过程是不需要的,只是我的强迫症发作了)



只有键盘隐藏了才算编辑完成,DidEndEditing方法才会被调用:

2014-02-15 23:44:46.448 HideKeyboardDemo[4371:70b] Did Begin Editing2014-02-15 23:44:48.525 HideKeyboardDemo[4371:70b] Hide Keyboard2014-02-15 23:44:48.527 HideKeyboardDemo[4371:70b] Did End Editing

所以在textFieldDidEndEditing方法中resign不会生效。


这种方法的好处是可以对所有委托为自己的UITextField组件有效。不足是对UITextView组件无效,而UITextViewDelegate中也没有shouldReturn的方法,虽然网上有文章是使用shouldChangeTextInRange:方法隐藏键盘,但是这样会覆盖掉TextView的换行功能,所以个人并不赞成用return键隐藏键盘。



方法三:使用UITextView的keyboardDismissMode

这个在我之前的一篇关于iOS 7 TextKit中的文章已经介绍过,这个是iOS 7的新特性,很不错,但是也有其不足。

使用非常简单:

    self.FirstTextView.keyboardDismissMode  = UIScrollViewKeyboardDismissModeOnDrag;    self.SecondTextView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

如果是UIScrollViewKeyboardDismissModeOnDrag,那么只要在UITextView中上下滚动一下(就像是滚动UIScrollView一样,里面的滚动条会动)就行了,这个很难截图,就不演示了。

如果是UIScrollViewKeyboardDismissModeInteractive,这个用文字表述有点吃力,其实就是先滚动下UITextView,然后手指贴着屏幕向下划,一直带动键盘退出屏幕,这个时候键盘看起来就像是具备交互性的一样,Interactive由此而来。例如:



优点:方便。

缺点:一,对UITextField无效。二,如果UITextView中的内容较少,无法超过UITextView的范围,也就是不会出现UIScrollView的滚动效果,那么上面的手势都会失效,这样我们又被迫回到方法一写个手势识别器了。例如:


连scroll的效果都出不来,更加谈不上dismiss keyboard了,这是其最大的不足,希望Apple会改进。



方法四:逆天的iPad键盘

方法四其实说不上是一个方法,就是iPad中的键盘不用我们费心而已,UITextView和UITextField通用:




小结

当然关于隐藏键盘还有很多解决方案,例如有人在touchesBegan方法中调用resignFirstResponder方法,个人并不赞成这种做法,因为在一些画图或有特定手势的程序中touchesBegan等方法有着特定的用途,无故加入个resignFirstResponder方法一来可能执行了不必要的代码,二来影响代码的美观性。有时候我们也可以在视图中直接加一个按钮,然后在里面调用resign方法就可以了。所以隐藏键盘的方案很多,本文的方法只是其中几个。


感觉iOS的API中隐藏键盘方面做得还是不够好,相信Apple以后会推出更加简洁的方法,甚至iPhone上面推出一个像iPad键盘那样的让键盘消失的键,耐心等吧。这段笔记先做到这里了。

最后根据国际惯例,上传了Demo,有兴趣的可以下载看看:点此进入下载页面



后记

2014/7/24

方法五:暴力的endEditing:方法

假设你的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

Run起来,无论你正在呼出哪个输入组件的键盘,只要在屏幕上滑或下滑手势,键盘立即隐藏。

本方法适用于视图中有一大堆输入控件的情况,此时可以节省大量的代码。

注意:该方法在iOS 2.0以后就可以用了,放心使用吧。具体的副作用暂时还不清楚,可能消耗的系统资源会比较多吧,而且如果传入的force参数为YES,某些UI组件正在执行的动作可能会被强行打断,感觉该方法不能滥用。


参考资料:

http://objdev.com/2013/11/Dismissing-iOS-Keyboard-Self-View-EndEditing

0 0
原创粉丝点击