为什么UIKit在动画取消后计算错误的安全区域?



有一个动画,动画视图从帧CGRect(x: 10, y: 10, width: 100, height: 100)到帧CGRect(x: 10, y: 10, width: 300, height: 300)。我使用UIViewPropertyAnimator来实现动画,下面是代码:

@objc func onTap() {
animator = UIViewPropertyAnimator(duration: 3, curve: .easeIn)

animator.addAnimations {
self.testView.frame = CGRect(x: 10, y: 10, width: 300, height: 300)
}

animator.addCompletion { pos in
print("test view frame:::", self.testView.frame)
print("test view safe frame:::", self.testView.safeAreaLayoutGuide.layoutFrame)
print("test view safe inset:::", self.testView.safeAreaInsets)
print("test view keyboard frame:::", self.testView.keyboardLayoutGuide.layoutFrame)
}
animator.startAnimation()
}

在动画过程中,还有一个按钮用于暂停动画和取消动画,代码如下:

@objc func cancelTheAnimation() {
animator.pauseAnimation()
animator.isReversed = true

let progress = animator.fractionComplete

animator.continueAnimation(
withTimingParameters: UICubicTimingParameters(animationCurve: .linear),
durationFactor: 1 - progress)
}
下面是控制台打印 的结果
------- animation completion ------
test view frame::: (10.0, 10.0, 100.0, 100.0)
test view safe frame::: (0.0, 37.0, 100.0, 63.0)
test view safe inset::: UIEdgeInsets(top: 37.0, left: 0.0, bottom: 0.0, right: 0.0)
test view keyboard frame::: (-10.0, 100.0, 390.0, 734.0)
------- animation completion ------
test view frame::: (10.0, 10.0, 100.0, 100.0)
test view safe frame::: (0.0, 37.0, 300.0, 263.0)
test view safe inset::: UIEdgeInsets(top: 37.0, left: 0.0, bottom: 0.0, right: 0.0)
test view keyboard frame::: (-10.0, 300.0, 390.0, 534.0)

结果第一次是正确的。然而,当我第二次取消动画时,结果是错误的,它应该是100而不是300(263 + 37)。

动画取消后,视图的帧被重置回其初始值,但安全区布局指南仍然是完成动画时设置的目标值。

这是UIKit的bug吗?

如果这不是UIKit的bug,我怎么解决这个问题,使安全区域与视图的帧匹配后取消动画

这个行为不是UIKit的bug。当您取消动画并将isReversed属性设置为true时,视图的框架将返回到其原始值

CGRect(x: 10, y: 10, width: 100, height: 100).

然而,视图的安全区域不受动画师的fraction complete属性的影响,因此它仍然反映动画结束时的值。要重置安全区域,您可以将视图的约束设置为与其框架匹配。我想这部分可以解决你的问题。

@objc func cancelTheAnimation() {
animator.pauseAnimation()
animator.isReversed = true
let progress = animator.fractionComplete
animator.continueAnimation(
withTimingParameters: UICubicTimingParameters(animationCurve: .linear),
durationFactor: 1 - progress)

testView.translatesAutoresizingMaskIntoConstraints = true
testView.frame = CGRect(x: 10, y: 10, width: 100, height: 100)
testView.layoutIfNeeded()
}

相关内容

  • 没有找到相关文章

最新更新