【发布时间】: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 错误。
【问题讨论】: