news 2026/9/1 20:45:14

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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 的效果。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 17:26:41

OpenClaw 安装教程(WSL 版本)

前提条件 Windows 10/11 系统已启用 WSL 2 并安装 Ubuntu 发行版 步骤 1&#xff1a;检查 WSL 状态 首先确认 WSL 是否已正确安装并运行&#xff1a; 打开 PowerShell运行命令&#xff1a; wsl --list --verbose 确保看到类似输出&#xff1a; NAME STATE …

作者头像 李华
网站建设 2026/9/1 20:44:19

(2)与Boost.Asio相关的函数

今天我们来学习与Boost.Asio相关的变量和函数 1. boost::asio::ip::address 表示一个通用 IP 地址对象&#xff0c;可以是 IPv4&#xff0c;也可以是 IPv6eg:boost::asio::ip::address ip_address boost::asio::ip::make_address("127.0.0.1");2. boost::system::er…

作者头像 李华
网站建设 2026/9/1 20:44:23

SQL注入绕过详解与防御机制

一、绕过方法 我们针对防护机制的不同&#xff0c;总结一下绕过手法 1-绕过注释符过滤 绕过方法&#xff1a;闭合引号法&#xff1a;不依赖注释符&#xff0c;而是通过巧妙构造输入&#xff0c;让原始的SQL语句自行闭合&#xff0c;从而语法正确。我们利用输入的内容1 and 11闭…

作者头像 李华
网站建设 2026/7/14 17:26:45

从“黑客”视角看安全:渗透测试到底在测什么?

从“黑客”视角看安全&#xff1a;渗透测试到底在测什么&#xff1f; “为什么斥巨资买了防火墙&#xff0c;黑客还是能如入无人之境&#xff1f;” 本文带你换上“连帽衫”&#xff0c;从零基础视角拆解渗透测试的思维逻辑&#xff0c;看清那些被你忽视的安全缝隙。 一、 什…

作者头像 李华
网站建设 2026/7/14 17:26:59

SL3051B与SL3052B脚位兼容SY8089高效同步降压DC-DC

脚位兼容SY8089&#xff0c;森利威尔SL3051B与SL3052B高效同步降压DC-DC转换器解析在便携式电子产品和物联网设备蓬勃发展的今天&#xff0c;电源管理芯片的性能直接决定了系统的续航能力、发热表现以及运行的稳定性。针对单节锂电池供电的应用场景&#xff0c;森利威尔原厂推出…

作者头像 李华