iOS 隐藏键盘

在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 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

所以在 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值