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

我们是工程师 ——加油 !

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

/*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_小马】🌹 哦

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容