子类化 UIButton 并覆盖触摸事件 - 不起作用
Subclassing UIButton and overriding touch events - not working
我需要为项目中的所有按钮制作比例 spring 动画。
所以我将 UIButton 子类化并覆盖触摸事件函数。
import UIKit
class UIAnimatedButton: UIButton {
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.transform = CGAffineTransformMakeScale(0.8, 0.8)
})
super.touchesBegan(touches, withEvent: event)
}
override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
UIView.animateWithDuration(0.5,
delay: 0,
usingSpringWithDamping: 0.2,
initialSpringVelocity: 6.0,
options: UIViewAnimationOptions.AllowUserInteraction,
animations: { () -> Void in
self.transform = CGAffineTransformIdentity
}) { (Bool) -> Void in
super.touchesCancelled(touches, withEvent: event)
}
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
UIView.animateWithDuration(0.5,
delay: 0,
usingSpringWithDamping: 0.2,
initialSpringVelocity: 6.0,
options: UIViewAnimationOptions.AllowUserInteraction,
animations: { () -> Void in
self.transform = CGAffineTransformIdentity
}) { (Bool) -> Void in
super.touchesEnded(touches, withEvent: event)
}
}
}
这在快速点击时效果很好,但是当我长时间(1-2 秒)触摸按钮时,我没有得到内部动作事件的修饰。
当我将它切换回常规 UIButton 时,一切正常。
知道为什么会这样吗?
我没有在 touchesCancelled
和 touchesEnded
方法的完成块中调用 super,而是在其中调用了 self.sendActionsForControlEvents(UIControlEvents.TouchUpInside)
。
还不确定具体原因,但您需要在动画外调用 super.touchesEnded(touches, with: event)
所以 (Swift 5)
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
UIView.animate(withDuration: 0.5,
delay: 0,
usingSpringWithDamping: 0.2,
initialSpringVelocity: 6.0,
options: UIView.AnimationOptions.allowUserInteraction,
animations: { () -> Void in
self.transform = CGAffineTransform.identity
}) { (Bool) -> Void in
}
super.touchesEnded(touches, with: event)
}
这是一种自 Swift 5 起有效的方法,因此 UIButton subclass 可以拦截其按钮推送,并将注册的 target/action 侦听器转发到按钮外部 class:
在子class编辑按钮的 UIView 超级视图中:
button.addTarget(self, action: #selector(buttonPushed),
for: .primaryActionTriggered)
在按钮 subclass 中,通过将此添加到 init()
方法来检测按钮按下:
let tapGestureRecognizer = UITapGestureRecognizer(target: self,
action: #selector(buttonPressed))
tapGestureRecognizer.numberOfTapsRequired = 1;
tapGestureRecognizer.numberOfTouchesRequired = 1;
self.addGestureRecognizer(tapGestureRecognizer)
使用处理程序在 subclass 内按下陷阱按钮:
@objc func buttonPressed() {
// .
// . (do whatever subclass needs to)
// .
self.sendActions(for: .primaryActionTriggered)
}
如果没有 sendActions,在 init 中添加的 gestureRecognizer 将阻止事件传播到 ResponderChain 中的消费者。
我需要为项目中的所有按钮制作比例 spring 动画。 所以我将 UIButton 子类化并覆盖触摸事件函数。
import UIKit
class UIAnimatedButton: UIButton {
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.transform = CGAffineTransformMakeScale(0.8, 0.8)
})
super.touchesBegan(touches, withEvent: event)
}
override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
UIView.animateWithDuration(0.5,
delay: 0,
usingSpringWithDamping: 0.2,
initialSpringVelocity: 6.0,
options: UIViewAnimationOptions.AllowUserInteraction,
animations: { () -> Void in
self.transform = CGAffineTransformIdentity
}) { (Bool) -> Void in
super.touchesCancelled(touches, withEvent: event)
}
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
UIView.animateWithDuration(0.5,
delay: 0,
usingSpringWithDamping: 0.2,
initialSpringVelocity: 6.0,
options: UIViewAnimationOptions.AllowUserInteraction,
animations: { () -> Void in
self.transform = CGAffineTransformIdentity
}) { (Bool) -> Void in
super.touchesEnded(touches, withEvent: event)
}
}
}
这在快速点击时效果很好,但是当我长时间(1-2 秒)触摸按钮时,我没有得到内部动作事件的修饰。 当我将它切换回常规 UIButton 时,一切正常。
知道为什么会这样吗?
我没有在 touchesCancelled
和 touchesEnded
方法的完成块中调用 super,而是在其中调用了 self.sendActionsForControlEvents(UIControlEvents.TouchUpInside)
。
还不确定具体原因,但您需要在动画外调用 super.touchesEnded(touches, with: event)
所以 (Swift 5)
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
UIView.animate(withDuration: 0.5,
delay: 0,
usingSpringWithDamping: 0.2,
initialSpringVelocity: 6.0,
options: UIView.AnimationOptions.allowUserInteraction,
animations: { () -> Void in
self.transform = CGAffineTransform.identity
}) { (Bool) -> Void in
}
super.touchesEnded(touches, with: event)
}
这是一种自 Swift 5 起有效的方法,因此 UIButton subclass 可以拦截其按钮推送,并将注册的 target/action 侦听器转发到按钮外部 class:
在子class编辑按钮的 UIView 超级视图中:
button.addTarget(self, action: #selector(buttonPushed), for: .primaryActionTriggered)
在按钮 subclass 中,通过将此添加到
init()
方法来检测按钮按下:let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(buttonPressed)) tapGestureRecognizer.numberOfTapsRequired = 1; tapGestureRecognizer.numberOfTouchesRequired = 1; self.addGestureRecognizer(tapGestureRecognizer)
使用处理程序在 subclass 内按下陷阱按钮:
@objc func buttonPressed() { // . // . (do whatever subclass needs to) // . self.sendActions(for: .primaryActionTriggered) }
如果没有 sendActions,在 init 中添加的 gestureRecognizer 将阻止事件传播到 ResponderChain 中的消费者。