【问题标题】:Why Does Autoreversing the Added Animation "Mess Up" the Final Result?为什么自动反转添加的动画会“搞砸”最终结果?
【发布时间】:2019-07-01 22:22:41
【问题描述】:

我有一个应用程序,它使用添加的动画来动画一个小的红色子视图。第一个动画将视图向下移动 100 点。第二个动画在中途点开始,将视图向右移动 100 点。向下和向右的动画是相加的,导致向右下方的对角线运动。此外,这两个动画都是自动反转的,以便视图恢复到其在小的绿色“标记”子视图顶部的原始位置。

从上面的 gif 可以看出,视图动画的行为与预期一致,直到自动反转完成,然后视图向左跳转(显然是 100 点)。通常这样的跳转是由于没有设置视图的状态来匹配动画的最后一帧。但是,动画师的完成方法确实正确设置了视图状态(?) - 这似乎由打印语句提供的信息所证实。

视图最终向左跳转的原因是什么?

请参阅下面的相关代码。完整的工程可以从GitHub下载

我有一种预感,两个动画闭包中对 UIView.setAnimationRepeatAutoreverses 的调用可能是罪魁祸首。我不清楚我在这方面所做的是否符合框架的期望。

class ViewController: UIViewController {

    private var markerView: UIView!
    private var animationView: UIView!

    override func viewDidLoad() {
        view.backgroundColor = .black
        view.addGestureRecognizer(UITapGestureRecognizer.init(target: self, action: #selector(tapGestureHandler)))

        let frame = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 10, height: 10)

        markerView = UIView(frame: frame)
        markerView.backgroundColor = .green
        view.addSubview(markerView)

        animationView = UIView(frame: frame)
        animationView.backgroundColor = .red
        view.addSubview(animationView)
    }

    @objc private func tapGestureHandler(_ sender: UITapGestureRecognizer) {
        animate()
    }

    // Move down; half way through begin moving right while still moving down.
    // Autoreverse it.
    private func animate() {
        let distance: CGFloat = 100
        let down = {
            UIView.setAnimationRepeatAutoreverses(true)
            self.animationView.center.y += distance
        }
        let right = {
            UIView.setAnimationRepeatAutoreverses(true)
            self.animationView.center.x += distance
        }

        print("\nCenter: \(self.animationView.center)")

        let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: down)
        animator.addAnimations(right, delayFactor: 0.5)
        animator.addCompletion { _ in
            print("Center: \(self.animationView.center)")
            self.animationView.center.x -= distance
            self.animationView.center.y -= distance
            print("Center: \(self.animationView.center)")
        }
        animator.startAnimation()
    }
}

更新 1

我添加了另外两个版本的 animate 方法,它们提供了丰富的信息。根据我从这两个版本中学到的知识,我改变了这个问题的标题。

animate2:对 UIView.setAnimationRepeatAutoreverses 的调用已在每个向下和右侧动画函数中被注释掉。此修改后的代码按预期运行。当然我们没有得到平滑的自动反转效果。

extension ViewController {

        private func animate2() {
        let distance: CGFloat = 100
        let down = {
            //UIView.setAnimationRepeatAutoreverses(true)
            self.animationView.center.y += distance
        }
        let right = {
            //UIView.setAnimationRepeatAutoreverses(true)
            self.animationView.center.x += distance
        }

        print("\nCenter: \(self.animationView.center)")

        let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: down)
        animator.addAnimations(right, delayFactor: 0.5)
        animator.addCompletion { _ in
            print("Center: \(self.animationView.center)")
            self.animationView.center.x -= distance
            self.animationView.center.y -= distance
            print("Center: \(self.animationView.center)")
        }
        animator.startAnimation()
    }
}

animate3:第二个(即右)动画的添加被注释掉。此修改后的代码按预期运行。当然,我们不会向右移动。

extension ViewController {

    private func animate3() {
        let distance: CGFloat = 100
        let down = {
            UIView.setAnimationRepeatAutoreverses(true)
            self.animationView.center.y += distance
        }
        let right = {
            UIView.setAnimationRepeatAutoreverses(true)
            self.animationView.center.x += distance
        }

        print("\nCenter: \(self.animationView.center)")

        let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: down)
        //animator.addAnimations(right, delayFactor: 0.5)
        animator.addCompletion { _ in
            print("Center: \(self.animationView.center)")
            self.animationView.center.y -= distance
            //self.animationView.center.x -= distance
            print("Center: \(self.animationView.center)")
        }
        animator.startAnimation()
    }
}

似乎在两个动画函数中调用 UIView.setAnimationRepeatAutoreverses 是“搞砸了”。我不清楚这是否可以正确地被视为 iOS 错误。

【问题讨论】:

    标签: animation ios12 swift4.2


    【解决方案1】:

    只需在您的 animate() 方法下注释该行 ::

            let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: down)
            animator.addAnimations(right, delayFactor: 0.5)
            animator.addCompletion { _ in
                print("Center: \(self.animationView.center)")
                //self.animationView.center.x -= distance //<--- Comment or remove this line.
                self.animationView.center.y -= distance
                print("Center: \(self.animationView.center)")
            }
    

    【讨论】:

    • 你好 Nikunj。按照您的建议进行操作会产生所需的视觉效果。但是打印语句报告的视图中心的值仍然与屏幕不匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    相关资源
    最近更新 更多