如何为UIView关键帧动画(`func UIView.animateKeyframes()`)设置动画曲线?

3

UIView关键帧动画允许您创建一系列步骤的视图动画。函数animateKeyframes(withDuration:delay:options:animations:completion:)具有类型为UIView.KeyframeAnimationOptions的选项参数。我期望它能让我选择一个整体的时间曲线来应用于组合的动画集。然而,它似乎应用了默认的缓入缓出动画曲线,并且似乎不允许您像UIView.animate()系列方法那样指定时间曲线。 如果我想要线性时间、仅缓入或仅缓出呢?

1个回答

5
有趣的是,UIView.animate() 方法的动画选项(类型为UIView.AnimationOptions)在你搞清楚如何将它们传递给 animateKeyframes(withDuration:delay:options:animations:completion:) 方法后就可以使用了。不幸的是,像线性、渐进或渐出等时间曲线的常量并不存在。 这篇Stack Overflow回答展示了如何将UIView.AnimationOptions 常量中的值“强制”转换到UIView.KeyframeAnimationOptions OptionSet 中。
extension UIViewKeyframeAnimationOptions {

    init(animationOptions: UIViewAnimationOptions) {
        rawValue = animationOptions.rawValue
    }

}

我进一步采取了行动,并为不同的时序函数定义了常量。(我不知道为什么苹果没有定义这些。看起来很荒谬,但事实就是这样。)

我对 UIView.KeyframeAnimationOptions 进行了扩展,如下所示:

extension UIView.KeyframeAnimationOptions {
    static var curveLinear: UIView.KeyframeAnimationOptions =
        UIView.KeyframeAnimationOptions(rawValue:UIView.AnimationOptions.curveLinear.rawValue)

    static var curveEaseInOut: UIView.KeyframeAnimationOptions =
        UIView.KeyframeAnimationOptions(rawValue:UIView.AnimationOptions.curveEaseInOut.rawValue)

    static var curveEaseIn: UIView.KeyframeAnimationOptions =
        UIView.KeyframeAnimationOptions(rawValue:UIView.AnimationOptions.curveEaseIn.rawValue)

    static var curveEaseOut: UIView.KeyframeAnimationOptions =
        UIView.KeyframeAnimationOptions(rawValue:UIView.AnimationOptions.curveEaseOut.rawValue)

    init(animationOptions: UIView.AnimationOptions) {
        self.init(rawValue: animationOptions.rawValue)
    }
}

使用该扩展,您可以像调用UIView.animate()方法一样使用时间曲线值:

UIView.animateKeyframes(withDuration: 2.0, delay: 0, options: [.curveLinear]) {
    // Your animation keyframe steps here
}

UIView.KeyframeAnimationOptions 中定义的一些其他标志可能也适用于 UIView.AnimationOptions。您可以使用允许将 UIView.AnimationOptions 映射到 UIView.KeyframeAnimationOptions 的方法,或者以与我添加计时曲线标志相同的方式向 UIView.KeyframeAnimationOptions 添加其他标志。


编辑:

我对 UIView.animate() 和 animateKeyframes() 选项中的标志感到好奇。我编写了一些代码来记录两个 OptionSet 的所有值,这就是我得到的结果:

KeyframeAnimationOptions:
option value 0x00000001 = layoutSubviews
option value 0x00000002 = allowUserInteraction
option value 0x00000004 = beginFromCurrentState
option value 0x00000008 = repeat
option value 0x00000010 = autoreverse
option value 0x00000020 = overrideInheritedDuration
option value 0x00000200 = overrideInheritedOptions

option value 0x00000000 = calculationModeLinear
option value 0x00000400 = calculationModeDiscrete
option value 0x00000800 = calculationModePaced
option value 0x00000C00 = calculationModeCubic
option value 0x00001000 = calculationModeCubicPaced

UIView.AnimationOptions:
option value 0x00000001 = layoutSubviews
option value 0x00000002 = allowUserInteraction
option value 0x00000004 = beginFromCurrentState
option value 0x00000008 = repeat
option value 0x00000010 = autoreverse
option value 0x00000020 = overrideInheritedDuration
option value 0x00000200 = overrideInheritedOptions

option value 0x00000040 = overrideInheritedCurve
option value 0x00000080 = allowAnimatedContent
option value 0x00000100 = showHideTransitionViews
option value 0x00000000 = curveEaseInOut
option value 0x00010000 = curveEaseIn
option value 0x00020000 = curveEaseOut
option value 0x00030000 = curveLinear
option value 0x00100000 = transitionFlipFromLeft
option value 0x00200000 = transitionFlipFromRight
option value 0x00300000 = transitionCurlUp
option value 0x00400000 = transitionCurlDown
option value 0x00500000 = transitionCrossDissolve
option value 0x00600000 = transitionFlipFromTop
option value 0x00700000 = transitionFlipFromBottom
option value 0x03000000 = preferredFramesPerSecond60
option value 0x07000000 = preferredFramesPerSecond30

两个选项集的前七个标志具有相同的名称和值。对于KeyframeAnimationOptions,0值是calculationModeLinear,对于UIView.AnimationOptions,则为curveEaseInOut。这导致关键帧和“常规”UIView动画都具有缓入缓出的时间控制。
所有其他常量的值在两个OptionSets中都是唯一的,这表明某些其他UIView.AnimationOptions也可能适用于关键帧动画。不过我只测试了时间曲线值,并且它们都能按预期工作。
编辑#2:
关键帧动画标志(如calculationModeLinear、calculationModeCubic和calculationModeCubicPaced)和View动画标志(如curveLinear、curveEaseInOut等)之间的交互方式并不明显,因为关键帧动画标志还涉及动画定时。我编写了一个测试应用程序来查看它们的效果。结果发现,UIView.AnimationOptions时间曲线标志影响整个关键帧动画的总体定时。(整个关键帧动画开始和停止的方式。)
您可以从github下载示例项目,在此处here
在使用任何立方关键帧动画选项之一以及缓入缓出UIView动画时间控制的组合中,有点难以看到缓入缓出。在采用关键帧calculationModeLinear模式时更容易看到缓入缓出效果。
以下是此组合的视频: enter image description here (请注意,青色正方形在动画矩形的右下角停下来后才返回到起始点。)

这是相当棒的东西,感谢您在这里发布。它非常有帮助! - Tiny Tim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接