自定义 UIButton 触发 IBAction 一次,然后再也不触发
Posted
技术标签:
【中文标题】自定义 UIButton 触发 IBAction 一次,然后再也不触发【英文标题】:Custom UIButton fires IBAction once, then never again 【发布时间】:2017-04-12 15:49:35 【问题描述】:我有一个名为 RippleButton 的自定义 UIButton 声明如下
public class RippleButton: UIButton
基本上它在触摸时会产生涟漪效果。我将此自定义按钮与以下 IBAction 一起使用
@IBAction func toggleMic()
if isMicrophoneOn
print("Stopped recording")
micIcon.image = UIImage(named: "mic_off")
micLabel.text = "Start Recording"
else
print("Started recording")
micIcon.image = UIImage(named: "mic_on")
micLabel.text = "End Recording"
isMicrophoneOn = !isMicrophoneOn
通过 Touch Up Inside 事件的设计编辑器将操作分配给按钮。
我的 RippleButton 像这样覆盖 touchesBegan
override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
super.touchesBegan(touches, with: event)
ripple.animate(sender: self, location: touches.first!.location(in: self))
当我第一次触摸按钮时,它会触发 IBAction 并从我的类 Ripple 中播放我的动画
func animate(sender: UIView, location: CGPoint)
ripple?.transform = CGAffineTransform(scaleX: 1, y: 1)
let size = Double(sender.bounds.width) > Double(sender.bounds.height) ? sender.bounds.width : sender.bounds.height
ripple?.frame = CGRect(x: location.x - size / 2, y: location.y - size / 2, width: size, height: size)
ripple?.layer.cornerRadius = size / 2.0
ripple?.alpha = CGFloat(opacity)
ripple?.backgroundColor = color
ripple?.transform = CGAffineTransform(scaleX: 0, y: 0)
container?.frame = CGRect(x: 0, y: 0, width: sender.frame.size.width, height: sender.frame.size.height)
container?.layer.cornerRadius = sender.layer.cornerRadius
container?.clipsToBounds = true
UIView.animate(withDuration: TimeInterval(speed),
delay: 0.0,
options: .curveEaseOut,
animations:
self.ripple?.transform = CGAffineTransform(scaleX: 2.5, y: 2.5)
self.ripple?.alpha = 0.0
)
ripple
是添加到container
的子视图,container
是添加到RippleButton
的视图
当我在第一次触摸后触摸它时,动画会播放,但 IBAction 不会触发。为什么它会触发一次,然后再也不会触发?
【问题讨论】:
与其覆盖touchesBegan
,不如直接在界面生成器中连接touchDown
事件?
因为我不想对所有使用此类的按钮都这样做。因为我打算在多个地方使用这个类,所以每次我实现这个类时,都会在 IB 中连接touchDown
很多重复的工作。
如果你只使用UIButton
可以吗?
你有没有试过在ripple.annimation
之后调用super.touchesBegan
,这个按钮有很多神奇的作用
@Alistra 是的,调用 IBAction 时默认的 UIButton 可以正常工作
【参考方案1】:
您说“涟漪是添加到容器的子视图,容器是添加到 RippleButton 的视图”......您是在“涟漪”效果之后删除该容器吗?也许这就是触摸事件。
【讨论】:
这就是问题所在。我正在添加容器来填充按钮,然后拦截触摸。通过添加container?.isUserInteractionEnabled = false
,我能够让事情按预期工作。【参考方案2】:
在 touchesEnded 中默认通过调用 self.sendActionsForControlEvents 触发动作。尝试覆盖 touchesEnded 和 touchesCancelled(使用超级调用)并在两者中设置断点。也许该活动将第二次取消。在这种情况下,您的动画会以某种方式干扰内部按钮状态的实现。这很难修复,因为 UIButton 是一个黑盒,更糟糕的是它的内部实现可能会改变。那么你应该从 UIControl 派生。
看看:4 different ways to handle tap
【讨论】:
很遗憾,此链接已损坏。以上是关于自定义 UIButton 触发 IBAction 一次,然后再也不触发的主要内容,如果未能解决你的问题,请参考以下文章
在主视图控制器的自定义单元格中使用来自 UIButton 的 IBAction
UIButton click(IBAction)没有以编程方式触发