问题
在iOS10和iOS11上运行相同的代码,我的UIViewPropertyAnimator在更改其.isReversed
属性后就有了不同的行为。
在iOS10上一切都很好。动画问题发生在iOS11上
条件
它适用于任何动画,不仅适用于特定的动画,而且可以通过观看动画和代码来验证。
它发生在模拟器和真实设备上。
详情
一旦创建了带有动画的UIViewPropertyAnimator,在其运行期间我只需调用.pauseAnimation()
并将.isReversed
属性更改为 true 。之后我恢复了动画调用:
continueAnimation(withTimingParameters parameters: UITimingCurveProvider?, durationFactor: CGFloat)
在iOS10上的这一点上,动画平滑地改变了他的诗句,在iOS11上它立即停止并以一点帧滞后反转。
如果在代码中我检查.fractionComplete
的值(在我的UIViewPropertyAnimator对象上调用,它会以0.0的百分比从1.0开始以1.0的形式返回动画的完成情况)
就在.continueAnimation(...
之后
- 在iOS 10上,它会保留一段时间,就好像动画正在继续,只有在一段时间后跳到他的补充。
- 在iOS 11上,它突然跳起来补充
在文档上有与此相关的非更新,只是UIViewPropertyAnimator的几个新属性但未使用,因为我以iOS10为目标
可能是一个错误,或者我错过了一些东西!?
小更新:刚刚测试过,在iOS 11.0.1和iOS 11.1 beta1上的行为相同
如评论中所链接的那样,只有非线性曲线才会发生这种情况!
答案 0 :(得分:6)
我一直在争论这个问题很长一段时间,但后来我注意到在iOS 11中添加到scrubsLinearly
的{{1}}属性:
默认为true。使动画师能够线性地或使用动画师的当前时间暂停和擦洗。
请注意,此属性的默认值为UIViewPropertyAnimator
,这似乎会导致与使用非线性动画曲线发生冲突。这也可以解释为什么在使用线性定时功能时不存在该问题。
将true
设置为scrubsLinearly
,动画师似乎按预期工作:
false
答案 1 :(得分:1)
在iOS 11上,fractionComplete
在您通过1 - originalFractionComplete
反转动画后将被撤消(即animator.isReversed = true
)。
持续时间少于0.1秒的春季动画将立即完成。
因此,您可能最初想要反转动画运行整个动画持续时间的90%,但在iOS 11上,反转动画的实际持续时间为10%,因为isReversed
已更改,并且10%持续时间小于0.1 s,所以动画将立即完成,看起来没有动画发生。
如何解决?
对于iOS 10向后兼容性,请在撤消动画之前复制fractionComplete
值并将其用于continueAnimation
。
e.g。
let fraction = animator.fractionComplete
animator.isReversed = true
animator.continueAnimation(...*fraction*...)
答案 2 :(得分:0)
我尝试了许多解决方案,但是没有人没有为我工作。我写了解决方案,现在一切都很好。我的解决方案:
拍摄屏幕图像并显示
完成动画
为旧状态启动新动画
暂停动画并设置进度(1-原始进度)
删除屏幕图像并继续动画
?
并且动画曲线选项必须为switch pan.state {
...
case .ended, .cancelled, .failed:
let velocity = pan.velocity(in: view)
let reversed: Bool
if abs(velocity.y) < 200 {
reversed = progress < 0.5
} else {
switch state {
case .shown:
reversed = velocity.y < 0
case .minimized:
reversed = velocity.y > 0
}
}
if reversed {
let overlayView = UIScreen.main.snapshotView(afterScreenUpdates: false)
view.addSubview(overlayView)
animator?.stopAnimation(false)
animator?.finishAnimation(at: .end)
startAnimation(state: state.opposite)
animator?.pauseAnimation()
animator?.fractionComplete = 1 - progress
overlayView.removeFromSuperview()
animator?.continueAnimation(withTimingParameters: nil, durationFactor: 0.5)
} else {
animator?.continueAnimation(withTimingParameters: nil, durationFactor: 0)
}
。
linear