在iOS开发中,一直存在这样一个问题,在TableViewCell上添加Button后,点击Button的时候,发现没有高亮效果,除非长按下去才能看到普通的Button选中效果。
原因解释:
iOS 6 的 UITableViewCell 子视图容器 (subviews) 是UITableViewCellContentView
iOS 7 后的 UITableViewCell 子视图容器 (subviews) 是UITableViewCellScrollView,是在UITableViewCell 和 conteneView之间的控制部分,因为iOS 7后添加了滑动编辑等操作,所以UITableviewCellScrollView会对触摸有相应的处理,具有一个属性 delaysContentTouches(默认为YES),会根据该属性的设置决定是否去判断,用户当前的 touch 究竟是滑动还是点击,应该是由于这部分的 delay 导致按钮的点击高亮效果被屏蔽了,但是点击事件还是存在的 。
经过纯代码和storyboard (xib) 两种方式重新编写Cell上带有Button的demo,验证这个问题确实都存在。
综合各类资料,得到并尝试了下面的解决方案:
仅在 Cell 中去修改代码,一层层向上寻找父View,直到UITableView(包括),凡是可以响应 delaysContentTouches 的都要将该属性设置为 NO,代码如下:
(void)cancelDelaysContentTouches{
id view = self.emptyStateView; //最外层的视图容器
while (view) {
if ([view respondsToSelector:@selector(setDelaysContentTouches:)]) {
[view setDelaysContentTouches:NO];
}
if ([view isMemberOfClass:[UITableView class]]) {
break;
}
view = [view superview];
}
}
其他解决方案:
1. 网上推崇最多的方式,在每个调用该类型 Cell 的 TableView 中将 delaysContentTouches 设置为NO,由于 UITableview 的 UITableViewWrapperView 也继承自 UIScrollView,所以需要使用一个循环来完成对于UITableview 中继承自 UIScrollView 的 View 中上述属性都要置为NO的操作,示例代码如下:
for (id obj in self.tableView.subviews) {
if ([obj respondsToSelector:@selector(setDelaysContentTouches:)]) {
[obj setDelaysContentTouches:NO];
}
} //**实测有效**,但是每个页面用到TableView都要设置,项目中涉及OC和Swift的多处调用,不方便,换思路。
2. 写一个UIButton的Category,将它的 touchBegan, touchCancel, touchEnded 方法重写,手动设置高亮效果。代码在参考文献中的 CSDN 博客中有提供,block中的延迟可以自己设置。实测有效,但是使用分类的实现影响了所有的 Button 效果,当前项目影响范围不可控,换思路。
3. 写一个Button的子类,重写分类中提到的方法,将Cell中的Button类型换掉,实测未生效。
参考资料:
https://stackoverflow.com/questions/19256996/uibutton-not-showing-highlight-on-tap-in-ios7 (Stack Overflow)
http://www.jianshu.com/p/6c0884c0933a -
https://zhidao.baidu.com/question/937679690539732732.html -百度知道
http://www.cnblogs.com/yu0806/p/4505795.html -转载的博客
http://blog.csdn.net/QearlYu/article/details/53391910 -CSDN博客