简体   繁体   English

UIViewPropertyAnimator 在 iOS10 和 iOS11 上反转动画的不同行为。 `isReversed` 和 `fractionComplete` 属性上的错误?

[英]UIViewPropertyAnimator different behaviour on iOS10 and iOS11 reversing an animation. Bug on `isReversed` and `fractionComplete` properties?

THE PROBLEM问题
Running the same code on iOS10 and iOS11 my UIViewPropertyAnimator has a different behaviour just after changing of his .isReversed property.在 iOS10 和 iOS11 上运行相同的代码,我的 UIViewPropertyAnimator 在更改他的.isReversed属性后有不同的行为。

Everything is ok on iOS10.在iOS10上一切正常。 The animation problem happens on iOS11动画问题发生在 iOS11

CONDITIONS条件
It's true for any animations, not only for a particular one, and it is verifiable both by watching the animation and within the code.它适用于任何动画,不仅适用于特定的动画,而且可以通过观看动画和在代码中进行验证。 It happens both on simulators and real devices.它发生在模拟器和真实设备上。

DETAILS详情
Once created a UIViewPropertyAnimator with his animation, during its running I just call .pauseAnimation() and change the .isReversed property to true .一旦用他的动画创建了一个 UIViewPropertyAnimator,在它运行期间我只需调用.pauseAnimation()并将.isReversed属性更改为true After that I resume the animation calling:之后我恢复动画调用:

continueAnimation(withTimingParameters parameters: UITimingCurveProvider?, durationFactor: CGFloat)

at this point on iOS10 the animation smoothly changes his verse, on iOS11 it stops immediately and reverses itself with a bit frames lag.此时,在 iOS10 上,动画平滑地改变了他的诗句,在 iOS11 上,它立即停止并以一点帧延迟反转自身。

If in code I check the value of .fractionComplete (called on my UIViewPropertyAnimator object it gives me back the completion of the animation in his percent value, starting from 0.0 and ending at 1.0) just after .continueAnimation(...如果在代码中我检查了.fractionComplete的值(在我的 UIViewPropertyAnimator 对象上调用,它会在.continueAnimation(...

- On iOS 10 it remains for a few moments like if the animation is continuing and only after some fractions of time jumps to his complementary. - 在 iOS 10 上,它会保持片刻,就像动画还在继续一样,只有在一小段时间之后才会跳转到他的补充。

- On iOS 11 it jumps suddenly on his complementary - 在 iOS 11 上,它突然跳到他的补充上


On the documentation there are non updates related to this, just a couple of new properties for the UIViewPropertyAnimator but not used because I'm targeting iOS10在文档中没有与此相关的更新,只有 UIViewPropertyAnimator 的几个新属性但没有使用,因为我的目标是 iOS10

Could be a bug or I'm missing something!?可能是错误或我遗漏了什么!?


Little update : just tested, same behaviour on iOS 11.0.1 and on iOS 11.1 beta1小更新:刚刚测试,在 iOS 11.0.1 和 iOS 11.1 beta1 上的行为相同

As linked in the comment, this happens only with a non-linear curve!正如评论中所链接,这只发生在非线性曲线上!

I have been fighting this for quite a while as well, but then I noticed the scrubsLinearly property that was added to UIViewPropertyAnimator in iOS 11:我也为此抗争了很scrubsLinearly ,但后来我注意到了在 iOS 11 中添加到UIViewPropertyAnimator中的scrubsLinearly属性:

Defaults to true.默认为真。 Provides the ability for an animator to pause and scrub either linearly or using the animator's current timing.为动画师提供线性或使用动画师的当前时间暂停和擦洗的能力。

Note that the default of this property is true , which seems to cause a conflict with using a non-linear animation curve.请注意,该属性的默认值为true ,这似乎会与使用非线性动画曲线产生冲突。 That might also explain why the issue is not present when using a linear timing function.这也可以解释为什么在使用线性计时函数时不存在此问题。

Setting scrubsLinearly to false , the animator seems to work as expected:scrubsLinearly设置为false ,动画师似乎按预期工作:

let animator = UIViewPropertyAnimator(duration: 0.25, curve: .easeOut) {
   ...
}
animator.scrubsLinearly = false
  1. On iOS 11, fractionComplete will be reversed (that is, 1 - originalFractionComplete ) after you reverse animation by animator.isReversed = true .在 iOS 11 上,通过animator.isReversed = true反转动画后, fractionComplete将反转(即1 - originalFractionComplete )。

  2. Spring animation that have less than 0.1s duration will complete instantly.持续时间少于 0.1 秒的弹簧动画将立即完成。

So you may originally want the reversed animation runs 90% of the entire animation duration, but on iOS 11, the reversed animation actually runs 10% duration because isReversed changed, and that 10% duration is less than 0.1s, so the animation will be completed instantly and looks like no animation happened.所以你最初可能希望反转动画运行整个动画持续时间的 90%,但是在 iOS 11 上,反转动画实际上运行了 10% 的持续时间,因为isReversed改变了,而这 10% 的持续时间小于 0.1s,所以动画将是立即完成,看起来没有动画发生。

How to fix?如何修复?

For iOS 10 backward compatibility, copy the fractionComplete value before you reverse animation and use it for continueAnimation .对于 iOS 10 向后兼容性,在反转动画之前复制fractionComplete值并将其用于continueAnimation

eg例如

let fraction = animator.fractionComplete
animator.isReversed = true
animator.continueAnimation(...*fraction*...)

I have tried many solutions, but no one didn't work for me.我尝试了很多解决方案,但没有一个不适合我。 I wrote my solution and everything is fine now.我写了我的解决方案,现在一切都很好。 My solution:我的解决方案:

  1. take an image of the screen and show it拍摄屏幕图像并显示它

  2. finish animation完成动画

  3. start new animation for old state为旧状态开始新动画

  4. pause the animation and set progress (1 - original progress)暂停动画并设置进度(1 - 原始进度)

  5. remove screen image and continue animation删除屏幕图像并继续动画

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

And the animation curve option must be linear .并且动画曲线选项必须是linear

    animator = UIViewPropertyAnimator(duration: 0.3, curve: .linear) {
        startAnimation()
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM