touchesBegan触发的按钮高亮动画失效问题排查
问题分析与解决办法
核心问题
你当前的动画不生效,是因为直接修改UIImageView的image属性不属于UIView动画支持的可动画属性。UIView的block动画只对frame、alpha、transform、backgroundColor这类属性生效,替换image不会触发平滑过渡,这就是动画没效果的原因。
可行解决方案
方案1:改用Alpha动画替代图片切换
不用替换image,提前把highlightBtn的image设置为半透明黑色(UIColor.black.withAlphaComponent(0.5).image()),然后通过动画修改它的alpha值,这样就能实现平滑的显示/隐藏效果:
func highlight(isHighlighted: Bool) { UIView.animate(withDuration: 0.08, delay: 0, options: [.allowUserInteraction, .curveEaseOut], animations: { self.highlightBtn?.alpha = isHighlighted ? 1.0 : 0.0 self.highlightBtn?.layer.compositingFilter = "softLightBlendMode" }) }
初始化时记得给highlightBtn设置好半透明黑色的图片,并且默认alpha设为0。
方案2:用CALayer过渡动画实现图片切换
如果必须切换图片,可以用CATransition来给UIImageView的layer添加过渡动画:
func highlight(isHighlighted: Bool) { let color = isHighlighted ? UIColor.black.withAlphaComponent(0.5) : .clear let transition = CATransition() transition.duration = 0.08 transition.type = .fade transition.timingFunction = CAMediaTimingFunction(name: .easeOut) self.highlightBtn?.layer.add(transition, forKey: "imageTransition") self.highlightBtn?.image = color.image() self.highlightBtn?.layer.compositingFilter = "softLightBlendMode" }
这种方式能让图片切换产生淡入淡出的动画效果。
方案3:优化自定义按钮类,动态生成高亮色
既然按钮背景色是API动态返回的,完全可以在自定义按钮里根据当前背景色自动生成加深的高亮色,不用额外加UIImageView,代码更简洁:
@IBDesignable class HighlightButton: UIButton { private var originalBackgroundColor: UIColor? override func awakeFromNib() { super.awakeFromNib() originalBackgroundColor = backgroundColor } override var isHighlighted: Bool { didSet { UIView.animate(withDuration: 0.08, delay: 0, options: [.allowUserInteraction, .curveEaseOut], animations: { if self.isHighlighted { // 生成加深的背景色(降低亮度30%) self.backgroundColor = self.originalBackgroundColor?.adjustBrightness(by: -0.3) self.layer.borderWidth = 1.8 } else { self.backgroundColor = self.originalBackgroundColor self.layer.borderWidth = 1.5 } }) } } } // 给UIColor加个扩展,用来调整亮度 extension UIColor { func adjustBrightness(by amount: CGFloat) -> UIColor { var hue: CGFloat = 0, saturation: CGFloat = 0, brightness: CGFloat = 0, alpha: CGFloat = 0 if getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) { return UIColor(hue: hue, saturation: saturation, brightness: max(0, min(1, brightness + amount)), alpha: alpha) } return self } }
这个方案直接利用按钮的isHighlighted状态触发动画,不用额外处理touch事件,系统会自动处理所有触摸场景(包括touch cancel),而且动态生成的高亮色和原背景色保持一致风格,完全满足你的需求。
内容的提问来源于stack exchange,提问作者PrateekS
相关产品推荐
相关产品推荐

