一、原理:
scrollView自带一个PanGesture滑动手势,滑动时修改scrollview的bounds.y,实现子视图有滑动效果。
参考:https://www.jianshu.com/p/964313cfbdaa
二、触摸事件打断
根据《事件传递 响应链》所知,自带的滑动手势会打断响应链中视图的touch方法,可以通过手势属性cancelsTouchesInView=NO ,让这个手势不打断响应者的touch方法。
参考:https://www.jianshu.com/p/b0884faae603
三、scrollView的一个机制
scrollView的属性
delaysContentTouches 和 canCancelContentTouches
控制事件响应交给scrollview子视图还是scrollView的手势。
从你的手指touch屏幕开始,scrollView开始一个timer,如果:
- 150ms内如果你的手指没有任何动作,消息就会传给subView。
- 150ms内手指有明显的滑动(一个swipe动作),scrollView就会滚动,消息不会传给subView。
- 150ms内手指没有滑动,scrollView将消息传给subView,但是之后手指开始滑动,scrollView传送touchesCancelled消息给subView,然后开始滚动。
delaysContentTouches:默认值为YES。如果设置为NO,则会立即把事件传递给subView。canCancelContentTouches:默认为YES,如果设置为NO,这消息一旦传递给subView,这scroll事件不会再发生。
参考:https://www.jianshu.com/p/2b171f6153ad
四、scrollview和子视图事件冲突
canCancelContentTouches用来控制scrollview的全局冲突设置,以下两个scrollview方法用来分开控制scrollview与子视图事件冲突
下面这个函数的功能是判断是否可以把touch 事件传递给子视图,即在他上面的视图。当返回是yes 的时候就表示可以,就当点击子视图view 的时候停止响应scroll事件,改而响应子视图的touch 事件,当为no 时则拒绝子视图响应,执行父视图的touch 事件
//scrollview的delaysContentTouches=NO时,会立刻调用这个方法,看是否滚动scrollview,用来控制子视图是否响应touch事件
- (BOOL)touchesShouldBegin:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view{
}
用来具体控制某个scrollview子视图是否打断touch,不打断子视图touch意味着触摸在这个子视图时,scrollview不会滑动
当UIScrollView将touch事件交给子view后,当手指发生滑动时,调用此方法,假如返回NO,则将touch事件交给view,如果返回YES,则交给UIScrollView处理,产生滑动。(但是前提是UIScrollView的canCancelContentTouches属性是YES才会调用这个方法,只要不是UIControll的子类,这个属性默认是YES。)
- (BOOL)touchesShouldCancelInContentView:(UIView *)view{
return NO;不打断子视图touch,scrollview不滑动
return YES;打断子视图touch,scrollview滑动}