很多情况下, 我们都会遇到在UITableView等UIScrollView可滚动控件上使用UITextField控件。这时候就会遇到如何取消UITextField的响应者身份。
比方说,我们在UITableViewCell上添加了一个UITextField用于接收用户的输入信息。可对于用户来说,最方便的就是点击其他地方就能完成输入,键盘自动隐藏。在iOS上来说,取消控件的响应者身份的方法由两种:
[view endEditing: YES];[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的方法,通过监听键盘事件来设置scrollView的contentInset。详情可以参见下方的链接。
在码代码的过程中,我是创建了一个RootViewController,然后在里面监听键盘事件,像Apple文档写的那样,监听了UIKeyboardDidShowNotification和UIKeyboardWillHideNotification这两个通知。然后在UITableViewCell中添加UITextField的控件。
可是在点击空白地方,想要结束输入隐藏键盘时,总是会触发到其他cell的点击事件。刚开始以为是cancelsTouchesInView属性引起的问题,就继续寻找其他方法代替。到后来发现,点击空白地方不放的话,键盘会马上隐藏起来,然后UITableView的contentInset会被设置回原来的值。此时tableView会恢复原状。我所以为的点击到空白地方,实际上是点击了cell!!猜想是UIKeyboardWillHideNotification对应的方法在点击释放之前完成了,导致点击穿透到cell中。
最后我将UIKeyboardWillHideNotification改为UIKeyboardDidHideNotification后,一切都变得正常了。花了好几个小时在这上面。呼~