UIbutton 在动画过程中也能响应事件,主要利用layer的hitTest方法
private var animationAllowUserInteractionKey: UInt8 = 0
extension UIButton {
var animationAllowUserInteraction:Bool{
set{
objc_setAssociatedObject(self, &animationAllowUserInteractionKey, newValue, .OBJC_ASSOCIATION_ASSIGN)
}
get{
if let ani = objc_getAssociatedObject(self, &animationAllowUserInteractionKey) as? Bool{
return ani
}
return false
}
}
open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
true
}
}
class DqAniRespondButton :UIButton{
/*
layer.presentation()这个方法返回值是当前Layer的副本,它包含当前事务开始时的所有属性,包括动画。它是了一个接近当前显示的layer的版本。如果该layer尚未提交,则返回nil。
它是个只读的,对它的任何方式修改都是无效的。
返回值的' sublayers', ' mask'和' superlayer'这些属性也是对应表示版本,也是只读的。
可以利用它调用-hitTest:将查询表示是否点击在当前layer(包括子layer)
该layer的所有子layers中包含p的layer,返回最顶层的layer上,如果都不包含则返回nil
*/
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else{
return
}
if animationAllowUserInteraction{
let p = touch.location(in: superview)
if ((self.layer.presentation()?.hitTest(p)) != nil) {
super.touchesBegan(touches, with: event)
}
}else{
super.touchesBegan(touches, with: event)
}
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
if animationAllowUserInteraction{
let p = convert(point, to: superview)
if ((self.layer.presentation()?.hitTest(p)) != nil) {
return true
}
}
return super.point(inside: point, with: event)
}
}