zhou的博客.

滑动视图子视图触摸时间延迟问题

字数统计: 508阅读时长: 1 min
2017/08/11 Share

场景:一个按钮放在UIScrollView里 或者 UITableViewCell里时,点击按钮 发现按钮的高亮状态延时,如果迅速的触摸一下按钮 甚至不回看到按钮的高亮状态。

原因:
UIScrollView:
属性delaysContentTouches,布尔类型,默认值为YES。值为YES时,UIScrollView会在接收到手势时延迟150ms来判断该手势是否能够出发UIScrollView的滑动事件;值为NO时,UIScrollView会立马将接收到的手势分发到子视图上。
(注:仅仅设置这个是不够的,你会发现如果想要拖动scrollView而起点落在其他有手势识别的视图上时会拖不动)
方法- (BOOL)touchesShouldCancelInContentView:(UIView *)view,此方法的重载是帮助我们完美解决问题的重点,决定手势是否取消传递到view上,拖动ScrollView时触发。返回NO时,拖动手势将留在ScrollView上,返回YES则将手势传到view上。(若view是UIControl,则默认返回YES)

UITableView:
不得不说,UITableView(包括UITableViewCell在内)在iOS7和iOS8中的视图结构是不同的,且存在着很多我们在编码时永远接触不到的视图,但我们可通过Debug将其subviews逐个逐个找出来。这关系到我们这个问题坑比较深的层次。
iOS7:UITableView中存在n+1个UIScrollView,一个是UITableView本身,另外n个存在于UITableViewCell与cell的contentView之间,类名为UITableViewCellScrollView,活的不久,仅存在于iOS7中,在iOS8中已被移除。
iOS8:UITableView中存在2个UIScrollView,一个是UITableView本身,另外一个存在于UITableView与UITableViewCell之间,类名为UITableViewWrapperView。需要注意的是,UITableViewWrapperView在iOS7中并不是一个UIScrollView。

解决办法:
将UIButton所有属于UIScrollView的父视图的delaysContentTouches属性设置成为NO。
2、继承UIScrollView或UITableView,并重写

1
- (BOOL)touchesShouldCancelInContentView:(UIView*)view方法,让其响应拖动方法。

demoCodes:
自定义一个UIScrollView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [superinitWithFrame:frame])
{
self.delaysContentTouches =NO;//禁止滑动延时

}
returnself;

}

//重载
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
if ([viewisKindOfClass:[UIButtonclass]])
{
returnYES;
}
return [supertouchesShouldCancelInContentView:view];

}

UITableViewCell 的实例代码也是一样的。

CATALOG
  1. 1. 场景:一个按钮放在UIScrollView里 或者 UITableViewCell里时,点击按钮 发现按钮的高亮状态延时,如果迅速的触摸一下按钮 甚至不回看到按钮的高亮状态。