美文网首页
UIScrollerView中的UISlider优先响应

UIScrollerView中的UISlider优先响应

作者: Farmers | 来源:发表于2019-04-19 17:20 被阅读0次

    一、背景:

    在项目开发时遇到一个问题,我在UIScrollerView中添加了一个UISlider的组件,在手势滑动的过程中,很难滑动到UISlider这个控件,经常是滑动的时候UIScrollerView进行了滚动,而UISlider这个控件没有滑动,让人很抓狂。

    二、分析

    网上说的通过重载UISlider的

    - (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value方法,改变滑块的响应区域,其实并没什么卵用。

    真正的问题还是出在了event响应上。

    我们从先探究UIScrollView的工作原理:

    UIScrollView有一个BOOL类型的tracking属性,用来返回用户是否已经触及内容并打算开始滚动,

    当手指触摸到UIScrollView内容的一瞬间,会产生下面的动作:

    列表内容

    拦截触摸事件,tracking属性变为YES

    一个内置的计时器开始生效,用来监控在极短的事件间隔内是否发生了手指移动

    case1:当检测到时间间隔内手指发生了移动,UIScrollView自己触发滚动,tracking属性变为NO,手指触摸下即使有(可以响应触摸事件的)内部控件也不会再响应触摸事件。

    case2:当检测到时间间隔内手指没有移动,tracking属性保持YES,手指触摸下如果有(可以响应触摸事件的)内部控件,则将触摸事件传递给控件进行处理。

    总结:当手指touch的时候,UIScrollView会拦截所有event,然后等待150ms,在这段时间内,如果没有手指没有移动,当时间结束时,UIScrollView会发送tracking event到子视图上,并且自身不滑动。在时间结束前,手指发生了移动,那么UIScrollView就会进行滑动,从而取消发送tracking。

    对于我们现在的情况,就是

    直接拖动UISlider,此时touch时间在150ms以内,UIScrollView会认为是拖动自己,从而拦截了event,导致UISlider接受不到滑动的event。但是只要按住UISlider一会再拖动,此时touch时间超过150ms,因此滑动的event会发送到UISlider上

    三、解决

    重写UIScrollView的hitTest方法:当滑动UISlider时,使UIScrollView不可滑动

    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

        /*

        直接拖动UISlider,此时touch时间在150ms以内,UIScrollView会认为是拖动自己,从而拦截了event,导致UISlider接受不到滑动的event。但是只要按住UISlider一会再拖动,此时此时touch时间超过150ms,因此滑动的event会发送到UISlider上。

        */

        UIView *view = [super hitTest:point withEvent:event];

        if([view isKindOfClass:[UISlider class]]) {

            //如果响应view是UISlider,则scrollview禁止滑动

            self.scrollEnabled = NO;

        } else {  //如果不是,则恢复滑动

            self.scrollEnabled = YES;

        }

        return view;

    }

    相关文章

      网友评论

          本文标题:UIScrollerView中的UISlider优先响应

          本文链接:https://www.haomeiwen.com/subject/wdscgqtx.html