UIScrollView中的按钮UIButton高亮状态延迟触发、响应慢问题分析

1. 问题发现

做项目时,在UICollectionCell中放置了三个按钮,然后设置了按钮的Normal状态和Highlighted状态图片,运行后,去操作的时候,发现点击了按钮,并没有高亮显示,但已触发了按钮的点击事件。后来经多次操作,才发现需要用手指点击按钮,并按住一下,才会显示高亮状态的图片。

2. 问题尝试解决

接下来想了想,以为是创建按钮时,设置的类型不对,结果把类型设置为Custom或System都不行。然后就去网上搜索有没有遇到这种问题的,最终找到了解决方法

3. 问题分析

在UIKit的 UIScrollView.h 中有以下属性或方法:

@property(nonatomic) BOOL delaysContentTouches;       // default is YES. if NO, we immediately call -touchesShouldBegin:withEvent:inContentView:. this has no effect on presses
@property(nonatomic) BOOL canCancelContentTouches;    // default is YES. if NO, then once we start tracking, we don't try to drag if the touch moves. this has no effect on presses

// override points for subclasses to control delivery of touch events to subviews of the scroll view
// called before touches are delivered to a subview of the scroll view. if it returns NO the touches will not be delivered to the subview
// this has no effect on presses
// default returns YES
- (BOOL)touchesShouldBegin:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event inContentView:(UIView *)view;
// called before scrolling begins if touches have already been delivered to a subview of the scroll view. if it returns NO the touches will continue to be delivered to the subview and scrolling will not occur
// not called if canCancelContentTouches is NO. default returns YES if view isn't a UIControl
// this has no effect on presses
- (BOOL)touchesShouldCancelInContentView:(UIView *)view;
3.1 delaysContentTouches

打开 Xcode,然后快捷键:⇧+⌘+0,可进入 Xcode 的开发者文档页面,然后输入:delaysContentTouches,进行搜索,可以看到:

Instance Property

delaysContentTouches

A Boolean value that determines whether the scroll view delays the handling of touch-down gestures.

Declaration
@property(nonatomic) BOOL delaysContentTouches;

Discussion
If the value of this property is YES, the scroll view delays handling 
the touch-down gesture until it can determine if scrolling is the intent. 
If the value is NO , the scroll view immediately calls [touchesShouldBegin:withEvent:inContentView:].
. The default value is YES.

a> delaysContentTouches为YES时,当UIScrollView接收到一个touch事件时,它会在一段时间内检测该touch是否进行了移动。假如移动了,则UIScrollView自身接受该touch事件,进行UIScrollView的滑动处理;否则,将touch事件传递给其子视图。
b> delaysContentTouches为NO时,当UIScrollView接收到一个touch事件时,它会立即调用touchesShouldBegin:withEvent:inContentView:方法,将touch事件传递下去。

由以上可知:就是因为有了一段检测的时间(延迟),才导致按钮没有立即显示高亮状态,因此,把UIScrollView的delaysContentTouches设置为NO,按钮就会立即显示高亮状态。

这样设置后,就会产生以下效果:

一旦手指触摸到按钮时,会立即显示高亮状态,但滑动不了UIScrollView。

这种效果总感觉有点不舒服,那能不能做到触摸按钮并滑动时,让UIScrollView也滑动呢?这就需要下面这个方法了。

3.2 touchesShouldCancelInContentView:

搜索:touchesShouldCancelInContentView:,可以看到:

Instance Method

touchesShouldCancelInContentView:
Returns whether to cancel touches related to the content subview and start dragging.

Declaration
- (BOOL)touchesShouldCancelInContentView:(UIView *)view;

Parameters
view
The view object in the content that is being touched.

Return Value
YES to cancel further touch messages to view, NO to have view continue to 
receive those messages. The default returned value is YES if view is 
not a UIControl object; otherwise, it returns NO.

Discussion
The scroll view calls this method just after it starts sending tracking 
messages to the content view. If it receives NO from this method, 
it stops dragging and forwards the touch events to the content subview. 
The scroll view does not call this method if the value of the 
canCancelContentTouches property is NO.

UIScrollView把touch事件传递给子视图后,当手指发生滑动时,UIScrollView会调用此方法,获取其返回值。
a> 若返回NO,即不取消子视图的事件,则UIScrollView停止拖拽并把touch事件交给子视图处理;
b> 若返回YES,也即取消子视图的事件,则由UIScrollView处理touch事件,进行滑动处理。

UIScrollView调用touchesShouldCancelInContentView:方法的前提是canCancelContentTouches为YES。但只要不是UIControl的子类,则该属性默认为YES。

4. 问题最终解决

1. 把 UIScrollView 的delaysContentTouches设置为NO;
2. 重写 UIScrollView 的touchesShouldCancelInContentView:方法,并返回YES;
即可实现:当点击按钮时,让按钮立即显示高亮状态,若移动手指,则能滑动 UIScrollView 的效果。

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

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,975评论 3 119
  • 如果生命中有一条线那一定是生命中缘,缘来缘去都以无法自拔。
    一念成魔一念成神阅读 187评论 0 0
  • 早上好!#幸福实修#~每天进步1%#幸福实修10班@胡玲美07--苏州# 20170801(09/30) 【幸福三...
    胡玲美hlm阅读 106评论 0 0
  • 一朝踏马去,何时把家回。 黄花遍满地,盼得几人归。
    一抹歆绿阅读 157评论 0 1