为什么自动反转添加的动画会“弥补”最终结果?

时间:2019-02-07 17:58:19

标签: animation ios12 swift4.2

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

simulator

从上面的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()
    }
}

enter image description here

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

enter image description here

在两个动画函数中调用UIView.setAnimationRepeatAutoreverses似乎是“使事情变得混乱”。我尚不清楚这是否可以正确地视为iOS错误。

1 个答案:

答案 0 :(得分:0)

只需在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)")
        }