美文网首页@IT·互联网程序员
【code_小马】解决ScrollView上按钮拦截响应的问题

【code_小马】解决ScrollView上按钮拦截响应的问题

作者: 曾经像素有点低 | 来源:发表于2016-12-28 23:47 被阅读3741次
    我们是工程师 ——加油 !

    老样子,先上代码解燃眉之急,具体思路解释 见下文

    /*UIScrollView高级用法:
    delaysContentTouches与
    canCencelContentTouches属性*/
    

    需求:

    UIScrollView+btns。点击btn高亮(Highlighted),滑动UIScrollView时取消高亮;

    分析:

    1.实现:点击btn高亮(Highlighted),且滑动UIScrollView时保持高亮状态,是不合理的,无法实现的。(ps还不如直接用cell或者btn的选中状态)
    2.实现:点击btn高亮(Highlighted), 滑动UIScrollView时取消高亮状态,是可以做到的。

    按照从不同的要素去解释原理:

    一、UIScrollView原理,以时间为轴线:

    从你的手指touch屏幕开始,scrollView开始一个timer,如果:

    1. 150ms内如果你的手指没有任何动作,消息就会传给subView。
    2. 150ms内手指有明显的滑动(一个swipe动作),scrollView就会滚动,消息不会传给subView。
    3. 150ms内手指没有滑动,scrollView将消息传给subView,但是之后手指开始滑动,scrollView传送touchesCancelled消息给subView,然后开始滚动。

    二、UIScrollView原理,以tracking属性为轴线:

    UIScrollView有一个BOOL类型的tracking属性,用来返回用户是否已经触及内容并打算开始滚动,我们从这个属性开始探究UIScrollView的工作原理:

    当手指触摸到UIScrollView内容的一瞬间,会有以下动作:

    • 拦截触摸事件
    • tracking属性变为YES
    • 一个内置的计时器开始生效,用来监控在极短的事件间隔内是否发生了手指移动

    case1:当检测到时间间隔内手指发生了移动,UIScrollView自己触发滚动,tracking属性变为NO,手指触摸下即使有(可以响应触摸事件的)内部控件也不会再响应触摸事件。
    case2:当检测到时间间隔内手指没有移动,tracking属性保持YES,手指触摸下如果有(可以响应触摸事件的)内部控件,则将触摸事件传递给控件进行处理。

    当你手指是缓慢划过或根本就没动,
    才会触发UIButton的触摸事件,这是case1的情况;
    
    有很多新闻类的App顶部都有一个滑动菜单栏,
    主要模型可能是由一个UIScrollView包含多个UIButton控件组成;
    当你操作的时候,手指如果是很迅速的在上面划过,
    会发现即使手指触摸的地方有UIButton,
    但是并没有触发该UIButton的任何触摸事件,
    这就是上面提到的case2。
    

    上面的工作原理其实有一个属性开关来控制:delaysContentTouches。
    解释:delaysContentTouches
    一个BOOL值,该值决定了滚动视图是否延迟了触控手势的处理。
    默认值为YES;如果设置为NO,则无论手指移动的多么快,
    始终都会将触摸事件传递给内部控件;
    设置为NO可能会影响到UIScrollView的滚动功能。

    delaysContentTouches的作用:
    这个标志默认是YES,使用上面的150ms的timer,
    如果设置为NO,touch事件立即传递给subView,
    不会有150ms的等待。

    delaysContentTouches :默认是YES;如果设置为NO,会马上执行touchesShouldBegin:withEvent:inContentView:

    - (BOOL)touchesShouldBegin:(NSSet<UITouch *> *)touches
                     withEvent:(UIEvent *)event 
                 inContentView:(UIView *)view;
    
    

    系统默认是允许UIScrollView,按照消息响应链向子视图传递消息的。(即返回YES)
    如果你不想UIScrollView的子视图接受消息,返回NO。

    应用描述(本人注释):这个方法是最先接收到滑动事件的(优先于button的
    UIControlEventTouchDown,以及
    - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event),
    如果返回YES,touche事件沿着消息响应链传递;
    如果返回NO,表示UIScrollView接收这个滚动事件,不必沿着消息响应链传递了。
    
    - (BOOL)touchesShouldCancelInContentView:(UIView *)view
    应用描述(本人注释):
    如果返回YES:(系统默认)是允许UIScrollView,按照消息响应链向子视图传递消息的
    如果返回NO:UIScrollView,就接收不到滑动事件了。
    

    再看另一个BOOL类型的属性canCancelContentTouches,
    从字面上理解是“可以取消内容触摸“,默认值为YES。
    这个BOOL类型的值控制content view里的触摸是否总能引发跟踪(tracking)
    cancelsTouches的作用:
    应用描述(本人注释):默认设置为YES,如果设置为NO,
    这消息一旦传递给subView,这scroll事件不会再发生。

    如果属性值为YES并且跟踪到手指正触摸到一个内容控件,这时如果用户拖动手指的距离足够产生滚动,那么内容控件将收到一个touchesCancelled:withEvent:消息,而scroll view将这次触摸作为滚动来处理。如果值为NO,一旦content view开始跟踪(tracking==YES),则无论手指是否移动,scrollView都不会滚动。

    • 简单点说,如果为YES,就会等待用户下一步动作,如果用户移动手指到一定距离,就会把这个操作作为滚动来处理并开始滚动,同时发送一个touchesCancelled:withEvent:消息给内容控件,由控件自行处理。如果为NO,就不会等待用户下一步动作,并始终不会触发scrollView的滚动了。
    • 可以用一段代码来验证并观察一下,定义一个YGScrollView继承自UIScrollView,一个YGButton继承自UIButton,然后重写部分方法:
    //【code_小马】
    YGScrollView.m
    
    - (BOOL)touchesShouldCancelInContentView:(UIView *)view
    {
        [super touchesShouldCancelInContentView:view];
        
        NSLog(@"code_小马:touchesShouldCancelInContentView");
        
        return YES;
    }
    
    - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [super touchesCancelled:touches withEvent:event];
        
        NSLog(@"code_小马:touchesCancelled");
    }
    
    
    //【code_小马】
    YGButton.m
    
    
    - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [super touchesCancelled:touches withEvent:event];
        
        NSLog(@"【code_小马:Button's touch cancelled】");
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [super touchesBegan:touches withEvent:event];
        
        NSLog(@"【code_小马:Button's touch began】");
    }
    
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [super touchesMoved:touches withEvent:event];
        
        NSLog(@"【code_小马:Button's touch moved】");
    }
    
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [super touchesEnded:touches withEvent:event];
    
        NSLog(@"【code_小马: Button's touch ended】");
    }
    
    

    其实就是在各个方法执行时打印出一个标记,

    • 当canCencelContentTouches值为YES时,
      用户触摸并移动手指再放开:输出台

    【code_小马: Button's touch began】
    【code_小马: Button's touch moved】
    ……
    【code_小马: Button's touch moved】
    code_小马:touchesShouldCancelInContentView
    【code_小马: Button's touch cancelled】

    • 当canCencelContentTouches值为NO时,
      用户触摸并移动手指再放开:输出台

    【code_小马:Button's touch began】
    【code_小马:Button's touch moved】
    ……
    【code_小马:Button's touch moved】
    【code_小马:Button's touch ended】

    【code_小马】iOS实用战术
    本文源码下载

    晌午时光

    • 很喜欢的一篇文章,拿出来和大家分享
      【第四集】

    那天我在巷口看见了如风拦住阿福,我刚想走过去却听到如风说:“别来我家了。”  “为什么?你姐是街里最漂亮的女孩子!我很中意她!”阿福笑着说。  “别来找我姐了。”如风说。  “阿风啊,你好福气的!我要是能天天和她睡一间屋,死了也心甘啦……”阿福仍继续说着,但他还没有说完,就被如风打倒在了地上。    “你疯啦!”阿福怒气冲冲的爬起来,挥起拳头就向如风打去,转眼间两个人就扭打成了一团。我惊讶的站在一旁,却没想过去拉开他们,因为我看到虽然阿福比如风高大,但却是如风占了上风,如风打得狠,拼命的狠。还有,就是我想知道,如风为什么为了不让阿福找我而和他打架。  不一会,阿福就告饶了,如风的脸也肿了起来,他不依不饶的说:“别再找我姐,不然我见一次打一次。”阿福连连答应,战战兢兢的走出小巷,看见我居然都没敢说一句话。    我没瞧他一眼就走到如风身边,摸摸他肿胀的脸说:“疼不?”     如风摇摇头,避开我的手。    我有点生气,讨厌他不理我的态度,板着脸说:“干吗打阿福?”    他不说话,我更生气,说:“怪不得虎哥安仔都不来找我了,都是你干的吧!”    如风抬起头,望着我,一字一句的说:“姐,只有我一个不好吗?”    他的眼神很纯净,纯净且坚定。    我和他对望。    只有如风一个人吗?他虽然不爱说话,但和他在一起却比和谈天说地的阿福在一起舒服,而这种舒服是无处不在的。    他会攒了好几月的钱,买我最爱吃的豆沙馅粽子回来。其实我从来没说过自己喜欢豆沙,能有粽子吃还挑选馅料是很奢侈的事情,只是很久以前那次吃粽子,我唯独吃了豆沙的两只,他便默默记下。    他会每天在学校门口等我下学,很自然的拿过我的书包,为我撑伞,踮起脚尖把奶奶给他的围巾围在我脖子上。    他会在我噘着嘴洗碗时,走到我身边把我挤开,粗手粗脚的在池子边干起来。当我不小心把盘子摔坏的时候,会大声对奶奶说:“是我做的!”    我突然发现,原来瘦瘦小小的如风一直站在我身边,当虎哥、安仔、阿福都不在时,他永远站在那里。而我,很开心他这样子。    “好,只有你一个!”我笑着捧着他的脸说,他很害臊似的躲开我的手,但眼神里是说不尽的快乐。    隔日,阿福妈见到奶奶啐道:“你家养了只狼仔!”奶奶没说如风什么,她总是不说他的,只是时不时的摇头。    此后,再也没有谁来找我了,我也渐渐不再和别人打交道。    那年,我13岁,魏如风12岁。    奶奶没有任何征兆的离开我们了。    开始她只是有些感冒,不停地咳嗽,我劝她去医院但她却死活不肯:“明日就好了,去花什么钱!你以为那些大夫就医得好?还不是骗你白花好些个!不如多喝些水哩!”    奶奶的明日迟迟不来,末日却终于临近。那天傍晚我们放学回来,奶奶在椅子上已经弥留了,她盯着弟弟看了很久,最后看了我一眼,叹了口气,没说一句话睁着眼睛就离开了。我当夜哭得死去活来,如风一直攥着我的手,片刻不离........................

    文章第三集
    文章第五集
    后续更新中,喜欢的话 请关注 🌹【code_小马】🌹 哦

    相关文章

      网友评论

        本文标题:【code_小马】解决ScrollView上按钮拦截响应的问题

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