[译]UIView动画|青训营笔记

282 阅读6分钟

这是我参与「第四届青训营」笔记创作活动的的第十八天。本篇文章将会翻译一篇讲解UIView动画的文章。原文链接:medium.com/doyeona/ani… (作者:Doyeona)

动画可以增加视觉线索,通知用户应用程序中正在发生的事情。在iOS中,动画被广泛用于重新定位视图、改变其大小、将其从视图层次中移除,以及隐藏它们。你可能会使用动画来向用户传达反馈信息或实现有趣的视觉效果。 --developer.apple

在iOS中,我们不需要写任何绘图代码,因为苹果为我们提供了它。我们只需要做的是触发动画,让Core animation处理单个帧的渲染。

3种类型的动画

  • UIKit
  • 核心动画
  • UIViewPropertyAnimator

什么时候使用,使用什么?

最后,所有UIKit风格的动画都被转换为Core Animation风格的动画。也就是说,所有的东西实际上都是用Core Animation来做动画的。--StackOverFlow

UIKit:动画是使用UIView对象进行的。视图支持一套基本的动画,涵盖许多常见的任务,如视图转换。它可以接受来自用户的事件,如触摸、点击和敲击,它在主线程中工作。

核心动画:在为底层属性制作动画时使用核心动画。它渲染、合成和动画视觉元素,提供高帧率和平滑的动画,而不会给CPU带来负担和拖慢应用程序。

UIViewPropertyAnimator:允许UIView属性的复杂和动态动画。

还在为使用什么而困惑吗?下面的图片将帮助你弄清楚!

图一: image.png

图二: image.png

  • 框架:修改这个属性来改变视图的大小和相对于父视图坐标的位置系统(如果transform属性不包含恒等转换就修改为bounds/center属性。)
  • 界限:修改此属性以改变视图的大小。
  • 中心:修改此属性以改变相对于父视图的坐标系的位置。
  • 转换:修改此属性以相对于其他中心点缩放、平移、旋转视图,此属性总是在2D空间中执行(如果要执行3D转换就必须要使用核心动画动画视图的层对象。)
  • alpha:修改此属性以逐渐改变视图的透明度。
  • 背景颜色:修改此属性来改变背景的颜色。
  • 内容拉伸:修改此属性以改变视图内容的拉伸方式以填充可用的空间。

如果你的视图承载了自定义图层对象--也就是没有关联视图的对象--你必须使用Core Animation来对它们的任何变化制作动画。

UIView的动画

使用UIKit,是实现你的代码的最简单的方法! 非常直接的API,可以作为一个初学者使用。

iOS上的所有动画都是使用Core Animation运行的。UIKit的基于块的动画方法只是一个方便的功能 虽然UIKit和Core Animation都提供了动画支持,但它们对视图层次结构的不同部分给予了访问。

class func animate(withDuration duration: TimeInterval, 
             delay: TimeInterval, 
           options: UIView.AnimationOptions = [], 
        animations: @escaping () -> Void, 
        completion: ((Bool) -> Void)? = nil)

duration 动画的总持续时间。

delay 在开始动画之前要等待的时间(秒)。

options 关闭的选项,表示你要如何执行动画 .autoreverse .repeater .curveEaseOut .curveEaseIn,点击查看更容:developer.apple.com/documentati…

对于过渡,选项以trans开头,例如:.transitionCrossDissolve

animations 一个块对象{},包含要提交给视图的变化。

completion 一个在动画序列结束时要执行的块对象。 让我们来编码吧! 那么如何用视图制作简单的动画呢?我在故事板中创建了一个标签和视图,并将它们连接到ViewController中。任务是:

1️. 改变视图的背景颜色

2️. 改变视图的高度和宽度的宽度

image.png image.png

当你运行代码时,视图的背景颜色会变成粉红色,视图的大小也会变大。但如果你想在这些动画之后马上做另一个动画怎么办?我喜欢改变视图的位置和视图的颜色。

我们可以使用一个完成处理程序,在动画之后马上给出另一个动画。

动画效果图可以点击此链接查看原图miro.medium.com/max/1348/1*…

image.png

在动画过程中,触摸事件变得不可用,所以要使它能够使用,你必须使allowUserInteraction = true。

好了!你知道它是如何工作的了吧? 试着改变数字和选项来适应它。另外,你有没有注意到还有一个使用SpringWithDamping的方法?

它使用对应于物理弹簧运动的定时曲线来执行视图动画。

image.png

这些是增加的参数。

dampingRatio为了使动画平滑减速而不产生振荡(以常规速度来回运动),使用1的值。

velocity 弹簧的初始速度。值为1对应于一秒钟内穿越的总动画距离。(当它接近0时变得更快)

查看动画效果图点击此链接:miro.medium.com/max/1348/1*…

image.png

我做了一个有点奇怪的动画,上面使用了.repeat, .autoreverse选项,所以这就是使用usingSpringWithDamping时的动画效果,你可以在一个数组中使用多个选项。

等等......如果我有多个代码块(像下面的代码那样的嵌套块)怎么办? 有什么办法可以改进代码吗?

@IBAction func animateBtnDidtouch(_ sender: Any) {
        UIView.animate(withDuration: 1, animations: {
            self.simpleView.backgroundColor = .brown     
        }){ _ in
            UIView.animate(withDuration: 1, delay: 0.25, options: [.autoreverse, .repeat], animations: {
                self.simpleView.frame.origin.y -= 20
            }){ _ in
                UIView.animate(withDuration: 1) {
                    //code
                }
            }
        }
    }

animateKeyframes

这就是为什么我们用keyframe来改善那些讨厌的代码块,只是在一个! AnimateKeyframe创建一个动画块对象,可以用来为当前视图设置基于关键帧的动画。

class func animateKeyframes(withDuration duration: TimeInterval, 
                      delay: TimeInterval, 
                    options: UIView.KeyframeAnimationOptions = [], 
                 animations: @escaping () -> Void, 
                 completion: ((Bool) -> Void)? = nil)

animations 一个包含要提交给视图的变化的块对象。通常,你调用addkeyframe(withRelativeStartTime:relativeDuration:animations:)方法。

addKeyframe:指定一个关键帧动画的单帧的时间和动画值。

frameStartTime: 开始指定动画的时间。这个值必须在0到1的范围内。

frameDuration:为指定值制作动画的时间长度。这个值必须在0到1的范围内,表示相对于整个动画长度的时间量。

animations: 一个包含你要执行的动画的块对象。这个参数不能为零。

 @IBAction func animateBtnDidTouch(_ sender: Any) {
        
        UIView.animateKeyframes(withDuration: 4, delay: 0, animations: {
            
            UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.25, animations: {
                self.animationView.backgroundColor = .magenta
            })
            
            UIView.addKeyframe(withRelativeStartTime: 0.25, relativeDuration: 0.25, animations: {
                self.animationView.alpha = 0.5
            })
            UIView.addKeyframe(withRelativeStartTime: 0.50, relativeDuration: 0.25, animations: {
                self.animationView.center.x = self.view.bounds.width - 100
            })
            UIView.addKeyframe(withRelativeStartTime: 0.75, relativeDuration: 0.25, animations: {
                self.animationView.center.x = self.view.bounds.width - 200
            })
        })
    }
}

最终得到的动画效果图片地址:miro.medium.com/max/1348/1*…

UIView.animateKeyframe(withDuration: 4, ....)意味着动画的总时长将是4秒

withRelativeStartTime是动画的开始时间。

relativeDuration是动画呈现的时间。如果它是0.25,那么它意味着4的四分之一,相当于1(秒)。

因此,每个addKeyframe将呈现一秒,而动画的总时长将是4秒。

动画工作:

  • 将背景颜色改为.magenda
  • 将alpha设为0.5
  • 改变X的中心