大概原理:
UIScrollView在滚动过程当中,其实是在修改原点坐标。当手指触摸后, scroll view会暂时拦截触摸事件,使用一个计时器。假如在计时器到点后没有发生手指移动事件,那么 scroll view 发送 tracking events 到被点击的 subview。假如在计时器到点前发生了移动事件,那么 scroll view 取消 tracking 自己发生滚动。
首先了解下UIScrollView对于touch事件的接收处理原理:
UIScrollView应该是重载了hitTest 方法,并总会返回itself 。所以所有的touch 事件都会进入到它自己里面去了。内部的touch事件检测到这个事件是不是和自己相关的,或者处理或者除递给内部的view。
为了检测touch是处理还是传递,UIScrollView当touch发生时会生成一个timer。
如果150ms内touch未产生移动,它就把这个事件传递给内部view
如果150ms内touch产生移动,开始scrolling,不会传递给内部的view。(例如, 当你touch一个table时候,直接scrolling,你touch的那行永远不会highlight。)
如果150ms内touch未产生移动并且UIScrollView开始传递内部的view事件,但是移动足够远的话,且canCancelContentTouches = YES,UIScrollView会调用touchesCancelled方法,cancel掉内部view的事件响应,并开始scrolling。(例如, 当你touch一个table, 停止了一会,然后开始scrolling,那一行就首先被highlight,但是随后就不在高亮了)
注:
hitTest的作用:当在一个view上添加一个屏蔽罩,但又不影响对下面view的操作,也就是可以透过屏蔽罩对下面的view进行操作,这个函数就很好用了。
hitTest的用法:将下面的函数添加到UIView的子类中,也就是屏蔽罩类中即可。
-(id)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = [super hitTest:point withEvent:event];
if (hitView == self)
{
return nil;
}
else
{
return hitView;
}
}