[iOS 10 day by day] Day 4:用 UIViewPropertyAnimator 编写动画

《iOS 10 day by day》是 shinobicontrols 公司编写的系列博客,介绍开发者需要了解的 iOS 10 新特性,每周更新。本系列翻译(文集地址)已取得官方授权。目录点此。仓薯翻译,欢迎指正:)

Shinobicontrols 为 iOS 和 Android 开发者提供高性能、响应式的 UI 控件 SDK,尤其是图表方面的控件。 官网 : shinobicontrols.com twitter : @shinobicontrols

曾经的黑暗年代

用基于 block 的 UIView animation 来编写 view 属性(frame, transform 等等)变化的动画非常简单。只需要短短几行代码:

你可以指定动画结束之后调用的 completion block。如果默认的匀速动画不能满足你的要求,还可以调整时间曲线。

但是,如果你需要一种自定义的曲线动画,相应的属性变化首先要快速开始,然后再急速慢下来,该怎么办呢?另外一个有点麻烦的问题是,怎么取消正在进行中的动画?虽然这些问题都可以解决,用第三方库或者创建一个新的 animation 来取代进行中的 animation。但苹果在 UIKit 中新加的组件能把这些步骤简化许多:进入UIViewPropertyAnimator的世界吧!

Animation 的新纪元

UIViewPropertyAnimator 的 API 设计得很完善,可扩展性也很好。它 cover 了传统 UIView animation 动画的绝大部分功能,并且大大增强了你对动画过程的掌控能力。具体来说,你可以在动画过程中任意时刻暂停,可以随后再选择继续,甚至还能在动画过程中动态改变动画的属性(例如,本来动画终点在屏幕左下角的,可以在动画过程中把终点改到右上角)。

为了探索这个新的类,我们来看几个例子,这几个例子都是演示一张图片划过屏幕的动画。如同所有 Day by Day 系列的文章,例子的代码可以在 Github 上下载到。这次我们用的是 Playground。

Playground 的准备

我们所有的 playground 页面都是让一个小忍者划过屏幕的动画。为了方便对比这些页面的代码,我们把公共部分的代码藏在 Sources 文件夹里。这样不仅能简化每个页面的代码,还能加快编译过程,因为 Sources 里的代码是预编译过的。

Sources 里包含一个简单的UIView子类,叫做NinjaContainerView。它的唯一功能就是添加一个 UIImageView 作为子 view,来显示我们的小忍者。我把忍者图片加到了 Resources 里。

现在,在每个 playground 页面里,我们可以复制粘贴以下代码:

这样我们就可以用上 Playground 强大的 “Live View” 功能,不用启动 iOS 模拟器就可以展示动画效果。尽管 Playground 还是有些不好用的地方,但用来尝试新功能是非常合适的。

要显示 Live View,点击菜单栏上的 View -> Assistant Editor -> Show Assistant Editor,或者点击右上角工具栏里两环相套的图标。如果在右半边的编辑器里没有看到 live view,要确保选中的是 Timeline 而不是 Manual —— 不得不承认我在这里浪费了一点时间。

从简单的开始

UIViewPropertyAnimator 的用法可以跟传统的 animation block 一样:

这会触发一个时长为 1 秒,时间曲线是缓进缓出的动画。动画的内容是闭包里的部分。

最简单的动画

注意我们是通过调用 startAnimation() 来显式启动动画的。另外一种创建 animator 的方法可以不用手动启动动画,就是 runningPropertyAnimator(withDuration:delay:options:animations:completion:)。确实有点长,所以可能还不如用第一种。

先创建好 animator ,再往上添加动画也很容易:

这两个 animation block 会同时进行。

两个 animation block

添加 completion block 的方法也很类似:

如果动画完整跑完的话,我们可以在控制台看到以下信息:

进度拖拽和反向动画

我们可以利用 animator 让动画跟随拖拽的进度进行:

Playground 总体来说是很好用的,而且还能在 Live View 里面添加可交互的 UI 控件。然而,接受响应事件就有点麻烦,因为我们需要一个 NSObject 的子类来监听诸如 .valueChanged 这种事件。所以,我们简单创建一个 EventListener,一旦触发它的 handleEvent 方法,它会调用我们的 eventFired 闭包。

这里 fractionComplete 值的计算方法跟时间没有关系了,所以我们的小忍者不再像之前指定的一样,会优雅地缓动。

Property animator 最强大的功能体现在它能随时打断正在进行的动画。让动画反向也非常容易,只需设置 isReversed 属性即可。

为了演示这一点,我们使用关键帧动画,这样就可以制作一个多阶段的动画了:

按下按钮的时候,animator 就会把动画反向进行,只要这一时刻动画还没结束。

自定义时间曲线

Property animator 在简洁优美的同时,还有很强的扩展性。如果你需要在苹果提供的时间函数之外自定义另一种时间曲线,只需传进一个实现 UITimingCurveProvider 协议的对象。大部分情况下用到的是 UICubicTimingParameters 或者 UISpringTimingParameters

例如,我们想让小忍者在划过屏幕的过程中,先快速加速,然后再慢慢停止。如下图的贝塞尔曲线所示(绘制曲线用了这个很方便的在线工具):

13227290-64bb5b74d13913a9

贝塞尔曲线

扩展阅读

新的 property animator 让编写动画更简单,它的 API 跟传统方法类似,还添加了打断动画、自定义时间曲线等功能。

Apple 为 UIViewPropertyAnimator 提供了详尽的文档。另外,也可以看看这场 WWDC 视频,深度解读这些新的 API,还讲了怎么用新的 API 来做 viewController 跳转的过渡动画。另外还有一些有趣的例子,例如一些简单的游戏

原文地址:iOS 10 Day by Day :: Day 4 :: UIViewPropertyAnimator

原作者:Sam Burnstone @sam_burnstone

ShinobiControls 官网:ShinobiControls.com twitter : @shinobicontrols

文集地址:iOS 10 day by day 仓薯翻译

本文地址:http://www.jianshu.com/p/4244cf130478

译者:戴仓薯

1 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部