在动画中点击 UIImage

Tapping a UIImage while it's being animated

我一直在尝试点击一个 UIImage,因为它会动画到我的屏幕顶部 print("Image Tapped"),但没有成功。

override func viewDidLoad() {
    super.viewDidLoad()

    redBalloon.image = UIImage(named: "redBalloon")
    redBalloon.contentMode = .scaleAspectFit
    redBalloon.frame = CGRect(x: Int(xOrigin), y: 667, width: Int(redBalloon.frame.size.width), height: Int(redBalloon.frame.size.height))

    UIView.animate(withDuration: 5, delay: 0, options: UIImageView.AnimationOptions.allowUserInteraction, animations: {
        self.redBalloon.frame = CGRect(x: Int(self.xEnding), y: -192, width: 166, height: 192)
    }, completion: {(finished:Bool) in
        self.endGame()
    })

    let imageTap = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
    redBalloon.isUserInteractionEnabled = true
    redBalloon.addGestureRecognizer(imageTap)
}

@objc func imageTapped(_ sender: UITapGestureRecognizer) {
    // do something when image tapped
    print("image tapped")
}

问题是图像视图不在您在动画期间看到它的位置(它在动画的终点)。所以你没有在图像视图所在的位置点击它,因此没有检测到点击。

因此,您必须 hit-test 表示层,或者,如果您不想这样做,则必须使用 UIViewPropertyAnimator 而不是调用 UIView.animate

作为第一种方法的示例,我将子类化 UIImageView。使您的 UIImageView 成为此子类的实例:

class TouchableImageView : UIImageView {
    override func hitTest(_ point: CGPoint, with e: UIEvent?) -> UIView? {
        let pres = self.layer.presentation()!
        let suppt = self.convert(point, to: self.superview!)
        let prespt = self.superview!.layer.convert(suppt, to: pres)
        return super.hitTest(prespt, with: e)
    }
}

不过个人觉得还是用UIViewPropertyAnimator简单很多。在这种情况下,不要 使您的 UIImageView 成为 TouchableImageView!你不想做额外的 hit-test 修改。让 属性 动画师完成所有工作:

    redBalloon.image = UIImage(named: "redBalloon")
    redBalloon.contentMode = .scaleAspectFit
    redBalloon.frame = CGRect(x: Int(xOrigin), y: 667, width: Int(redBalloon.frame.size.width), height: Int(redBalloon.frame.size.height))

    let anim = UIViewPropertyAnimator(duration: 5, timingParameters: UICubicTimingParameters(animationCurve: .easeInOut))
    anim.addAnimations {
        self.redBalloon.frame = CGRect(x: Int(xEnding), y: -192, width: 166, height: 192)
    }
    anim.addCompletion { _ in
        self.endGame()
    }

    let imageTap = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
    redBalloon.isUserInteractionEnabled = true
    redBalloon.addGestureRecognizer(imageTap)
    anim.startAnimation()