键盘事件

1,228 阅读2分钟

很多情况下, 我们都会遇到在UITableViewUIScrollView可滚动控件上使用UITextField控件。这时候就会遇到如何取消UITextField的响应者身份。

比方说,我们在UITableViewCell上添加了一个UITextField用于接收用户的输入信息。可对于用户来说,最方便的就是点击其他地方就能完成输入,键盘自动隐藏。在iOS上来说,取消控件的响应者身份的方法由两种:

  1. [view endEditing: YES];
  2. [view resignFirstResponder];

0x01 cancelTouchesInView

在经过尝试和寻找答案的过程中,哪怕是在SO上面,大多数人都是建议给view添加一个tap的手势。通过tap来捕获点击事件,然后执行resignFirstResponder方法。

可是,比方说在UITableView上的话,你会发现当添加上tap手势以后,原来的delegate方法tableView:didSelectedRowAtIndexPath:并不会执行了。这是因为tap手势拦截了点击事件。

不过幸运的是,还有cancelsTouchesInView这个属性可以控制。tap.cancelsTouchesInView = NO;这样设置的话,一切就会变得正常。

cancelsTouchesInView这个属性的话,默认情况是YES。设置为NO的话,表示手势会被当前控件响应后传递到下一层中。


0x02 hitTest:withEvent

除了设置cancelTouchesInView的属性之外,我们还能继承UITableView,利用hitTest:withEvent的方法来捕获动作事件

@implementation BaseTableView

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    id view = [super hitTest:point withEvent:event];
    if (![view isKindOfClass:[UITextField class]] || ![view isKindOfClass:[UITextView class]]) {
        [self endEditing:YES];
    }
    return view;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

@end

0x03 避免遮挡

使用UITableView或者UICollectionView的时候,如果UITextField在屏幕之外的话,在进行输入的时候难免会被键盘遮挡住。Apple在中提供了demo的方法,通过监听键盘事件来设置scrollViewcontentInset。详情可以参见下方的链接。

在码代码的过程中,我是创建了一个RootViewController,然后在里面监听键盘事件,像Apple文档写的那样,监听了UIKeyboardDidShowNotificationUIKeyboardWillHideNotification这两个通知。然后在UITableViewCell中添加UITextField的控件。

可是在点击空白地方,想要结束输入隐藏键盘时,总是会触发到其他cell的点击事件。刚开始以为是cancelsTouchesInView属性引起的问题,就继续寻找其他方法代替。到后来发现,点击空白地方不放的话,键盘会马上隐藏起来,然后UITableViewcontentInset会被设置回原来的值。此时tableView会恢复原状。我所以为的点击到空白地方,实际上是点击了cell!!猜想是UIKeyboardWillHideNotification对应的方法在点击释放之前完成了,导致点击穿透到cell中。

最后我将UIKeyboardWillHideNotification改为UIKeyboardDidHideNotification后,一切都变得正常了。花了好几个小时在这上面。呼~

参考链接

Managing the Keyboard