iOS冷知识:任意设置UIScrollView的滑动触摸区域。

前言

   前言: UIScrollViewUITableView是iOS中最常用的控件。而UITableView又是继承自UIScrollView的,所以一个iOS程序员的工作可能会有很长一段时间是在折腾一个或多个UIScrollView。了解UIScrollView的属性和特点很有必要!
   在我们通常的认知里,想要一个UIScrol lView随着我们的手指滑动而滑动,那么我们的手指必须在UIScrollView的范围内滑动并且这个scrollview上层没有任何别的view遮挡。但是其实我们是有办法改变这个范围的,使得即使我们在UIScrollView以外的地方滑动依旧可以使得UIScorllview产生滑动。

实现

   如图我们在一个viewcontroller的view上添加了一个scrollview,然后又addsubview一个白色的topview遮挡scrollview,那么当我们尝试滑动scrollview的时候会发生以下情况:

未命名.gif

   原因是我们都知道了,根据iOS响应链的规则通过hit-test找到找到点击区域最上层的view,然后通过最上层的view找到firstResponder,让firstResponder处理这个事件。
   响应链条在本次滑动事件的处理流程大致如下:当我们尝试在topview滑动的时候,会使用hit-test来找出最上层的view响应当前滑动事件。监测到白色topview是最上层的view所以会把事件交给白色topview,但是topview并没有不处理事件,所以需要向它nextResponder也就是它的superview,viewcontroller的view来处理,以此类推,发现并没有view能够处理这个事件,所以这个事件被作废。我们的scrollview全程并未参与自然无法接受事件
   关于响应链的详细原理这里并不展开。

转机

   点开UIScrollView.h,我们能看到UIScrollView有一个属性panGestureRecognizer:

@property(nonatomic, readonly) UIPanGestureRecognizer *panGestureRecognizer API_AVAILABLE(ios(5.0));

打印该属性如下:

(lldb) po self.scrollView.panGestureRecognizer
<UIScrollViewPanGestureRecognizer: 0x7fb24a7080a0; state = Possible; delaysTouchesEnded = NO; view = <UIScrollView 0x7fb24c01b200>; target= <(action=handlePan:, target=<UIScrollView 0x7fb24c01b200>)>>

发现这个手势是一个UIScrollViewPanGestureRecognizer,也就是处理UIScrollView滑动的手势,它的view是
view = <UIScrollView 0x7fb24c01b200>;
也就是UIScrollView本身。这也就是为什么UIScrollView的滑动一定要在UIScrollView范围内。
既然UIScrollView把处理滑动的手势暴露给我们了,那我们是不是可以把这个手势添加到别的view上呢?
答案是:可以!
正如我们刚才说的响应链的原理,我们只要把UIScrollViewpanGestureRecognizer添加到topview和scrollview的共同父view,也就是这里的UIViewController的view上就可以实现点击整个屏幕都能滑动UIScrollView了!

    [self.view addGestureRecognizer:self.scrollView.panGestureRecognizer];

再看一下效果:


滑动.gif

更加惊喜的是,我们不仅可以修改UIScrollView的手势触发view为任意view,而且可以得到这个手势的回调:

[self.scrollView.panGestureRecognizer addTarget:self action:@selector(scrollViewPan:)];

- (void)scrollViewPan:(UIPanGestureRecognizer*)gesture
{
    if (gesture.state == UIGestureRecognizerStateBegan) {
    }else if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == 
    }else if (UIGestureRecognizerStateChanged) {
    }
}

不用担心这个回调会影响scrollview本身的滑动,他们并不会冲突。

拓展

由此拓展开来,我们可以把 scrollview的panGerturerecognizer属性添加到任意我们想要添加的view上,实现更加有趣的效果,比如:

修改滑动区域.gif

结论:改变UIScrollView的滑动手势panGerturerecognizer的作用view,就可以改变UIScrollView的滑动手势响应view,实现在任意view上响应UIScrollView的滑动手势

最后附上demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。