子类化UIButton并重写触摸事件-无法工作

12

我需要在项目中为所有的按钮制作一个弹簧动画。所以我继承了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秒)时,我没有得到“touch up inside”的动作事件。 当我将其切换回常规的UIButton时,一切正常。

有何想法为什么会发生这种情况?


除非文档另有规定,否则在覆盖方法中要做的第一件事是调用 super。在动画块内调用它有点奇怪。 - LuckyStarr
如果我在动画结束前调用 super,那么动画就不会播放了。你有什么办法来制作这个动画吗? - ilan
1
不要覆盖UIGestureRecognizer方法,而是尝试使用UIControl类的方法beginTrackingWithTouch:withEvent:continueTrackingWithTouch:withEvent:endTrackingWithTouch:withEvent:,其中UIButton是其子类。 - LuckyStarr
这个不起作用...动画没有被执行。 - ilan
3个回答

9

touchesCancelledtouchesEnded方法的完成块中,我调用了self.sendActionsForControlEvents(UIControlEvents.TouchUpInside)而不是调用super。


2

目前还不确定原因,但你需要在动画外调用super.touchesEnded(touches, with: event)

因此(Swift 5)

最初的回答:

还不确定原因,但需要在动画外调用super.touchesEnded(touches, with: event)

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)
}

0

这是一种在Swift 5中有效的方法,因此UIButton子类可以拦截其按钮推送,并将已注册的目标/操作侦听器转发到按钮类外部:

在子类化按钮的UIView superview中:
button.addTarget(self, action: #selector(buttonPushed), for: .primaryActionTriggered)
在按钮子类中,通过将以下内容添加到init()方法来检测按钮按下: let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(buttonPressed)) tapGestureRecognizer.numberOfTapsRequired = 1; tapGestureRecognizer.numberOfTouchesRequired = 1; self.addGestureRecognizer(tapGestureRecognizer)
使用处理程序在子类中捕获按钮按下:
@objc func buttonPressed() { // . // . (做任何子类需要的事情) // . self.sendActions(for: .primaryActionTriggered) }

如果没有使用sendActions,那么在init中添加的gestureRecognizer将会阻止事件传递到ResponderChain中的消费者。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接