我有一个应用程序,可以使用添加的动画为小的红色子视图设置动画。第一个动画将视图向下移动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错误。
答案 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)")
}