iOS Swift如何实现按钮高亮背景色点击后持续2秒恢复
实现方案
你提到的定时器思路是可行的,结合UIButton原生的状态管理优化后可以避免重复触发、状态冲突等问题,以下是完整实现:
1. 基础能力:不同状态下设置对应背景色
先通过扩展给UIButton增加按状态设置背景色的能力,不需要手动监听高亮状态变化:
extension UIButton { /// 给指定状态设置背景色 func setBackgroundColor(_ color: UIColor, for state: UIControl.State) { // 将颜色转为1x1的背景图赋值给对应状态 let image = UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1)).image { context in color.setFill() context.fill(CGRect(x: 0, y: 0, width: 1, height: 1)) } setBackgroundImage(image, for: state) } }
初始化按钮时直接调用即可实现高亮自动变色:
// 普通状态背景色 button.setBackgroundColor(.systemBlue, for: .normal) // 高亮状态背景色 button.setBackgroundColor(.systemRed, for: .highlighted)
2. 扩展能力:点击后高亮状态延迟2秒恢复
自定义UIButton子类,拦截点击事件和状态变更逻辑,避免连续点击导致的状态混乱:
class DelayRecoverButton: UIButton { /// 标记是否处于延迟恢复状态,避免状态冲突 private var isInDelayPhase = false /// 高亮恢复延迟时长,可自定义 var delayDuration: TimeInterval = 2 override var isHighlighted: Bool { didSet { // 延迟恢复阶段不响应系统的高亮状态切换 guard !isInDelayPhase else { return } super.isHighlighted = isHighlighted } } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesEnded(touches, with: event) // 进入延迟恢复状态,强制保持高亮样式 isInDelayPhase = true isHighlighted = true // 延迟指定时长后恢复原状态 DispatchQueue.main.asyncAfter(deadline: .now() + delayDuration) { [weak self] in guard let self = self else { return } self.isInDelayPhase = false self.isHighlighted = false } } }
使用时直接把按钮的类设置为DelayRecoverButton即可,原有addTarget的点击事件逻辑不受影响。
注意事项
- 不建议用Timer实现延迟逻辑,
DispatchQueue.main.asyncAfter更轻便,无需手动处理RunLoop绑定和内存释放问题 - 如果需要支持连续点击,可以在
touchesEnded开头加判断:如果isInDelayPhase为true则直接return,避免重复触发延迟逻辑 - 如果需要圆角等特殊样式,直接设置按钮的layer属性即可,背景色切换逻辑不受影响
内容的提问来源于stack exchange,提问作者liangdapang
相关产品推荐
相关产品推荐

