我有这个简单的代码:
func tappedButton() {
self.button.alpha = 1.0
UIView.animate(withDuration: 1.0, delay: 4.0, options: .curveLinear, animations: {
self.button.alpha = 0.0
}) { _ in }
}
此功能旨在在隐藏按钮之前再次显示按钮4秒钟(带有1秒动画)。但是,虽然在这4秒钟内完全可见该按钮,但是点击它不再起作用。
感谢您的帮助。
答案 0 :(得分:0)
根据有关UIView https://developer.apple.com/documentation/uikit/uiview/1622469-hittest的hittest(_:with :)方法的文档,
此方法将忽略隐藏的视图对象,禁用的用户交互或alpha级别小于0.01的视图对象。确定点击时,此方法不会考虑视图的内容。因此,即使指定点位于该视图内容的透明部分中,该视图仍然可以返回。
这意味着将不会触摸任何带有alpha 0.0的视图,尤其是按钮。
但是,这里的问题是,至少对于您来说,该按钮仍然可见。之所以会出现这种 odd 行为,是因为在动画开始时,按钮的实际alpha值已经已经设置为0.0。动画通过更改视觉层次并通过为函数提供的参数转换差异来起作用。在您的情况下,您有两种状态:一个带有可见按钮的视图和另一个没有该按钮的视图。仅可视部分具有动画效果,但已经设置了相应的值。一个解决方案是:
func tappedButton() {
self.button.alpha = 1.0
UIView.animate(withDuration: 1.0, delay: 4.0, options: .curveLinear, animations: { [weak self] in
self?.button.alpha = 0.01
}) { [weak self] _ in self?.button.alpha = 0.0 }
}
编辑:此解决方案似乎很简单,但可行。我使用这种方法是因为完成处理程序总是使用true
值来调用。
func tapped() {
let duration = 1.0
let delay = 2.0
let delayDuration = delay + duration
UIView.animate(withDuration: duration, delay: delay, options: [.curveLinear, .allowUserInteraction], animations: { [weak self] in
self?.saveButton.alpha = 0.1
})
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delayDuration, execute: { [weak self] in
self?.saveButton.alpha = 0.0
})
}
答案 1 :(得分:0)
您需要在选项中使用allUserInteraction并检查是否有触摸。立即添加了动画,尽管您看到了系统按钮,但该按钮已被隐藏。这是什么意思?这意味着您正在看电影。但是至少在启用userInteraction的情况下,您可以检查触摸事件。很棒,但是我们如何知道按钮是否真正显示呢?好吧,您最有可能必须使用两种不同的检查。一种检查按钮的真实UIView alpha,另一种检查显示层的不透明度。我从未完全研究过UIView动画和Core Animation之间的联系,只是我认为UIView动画是Core Animations的包装。 UIView动画肯定会立即更新视图模型。因此,alpha动画很可能会解释为图层上的不透明度动画。有了此功能,我们就可以检查表示层在触摸时的不透明度,即使视图模型认为alpha为0,也可以看到单击了按钮。只要不透明度大于0,就可以在表示层进行检查。所以你去。
import UIKit
class ViewController: UIViewController {
lazy var testButton : UIButton = {
let v = UIButton(frame: CGRect(x: 20, y: 50, width: self.view.bounds.width - 40, height: 50))
v.backgroundColor = UIColor.blue
v.addTarget(self, action: #selector(buttonClicked), for: .touchUpInside)
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(testButton)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 1.0, delay: 4.0, options: .allowUserInteraction, animations: {
self.testButton.alpha = 0
}, completion: nil)
//test the layer
//test the layer for opacity
if let presentation = testButton.layer.presentation()?.animation(forKey: "opacity"){
print("the animation is already added so normal clicks won't work")
}
}
@objc func buttonClicked(){
print("clicked")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
if let touch = touches.first{
let location = touch.location(in: self.view)
if self.testButton.frame.contains(location){
//but what you might not know is the animation is probably already running
//and so the check above misses this
if let buttonPres = testButton.layer.presentation(),
let _ = buttonPres.animation(forKey: "opacity"),
let opacity = buttonPres.value(forKey: "opacity") as? CGFloat{
if opacity > 0{
buttonClicked()
}
}
}
}
}
}