[Animations] 快速上手 iOS10 属性动画
概述
详细
基础动画, 核心动画到自定义转场动画其实都不是什么新东西了, 所以我也是草草看一遍就能够读个大概, 但今天要说的UIViewPropertyAnimator, 是iOS10新的API, 其他的好处我还不太清楚, 但抽象动画逻辑和监控动画的进程上真的是方便很多。

一、准备工作
对于属性动画来说, 真的是个新知识, 想必会用的还不多, 我也是近期才有涉及, 理解不周还望大伙指点一二, 之前我们要做一些稍微高级的动画都会使用核心动画的方法, 但是核心动画有一个致命的弱点, 就是假象和被打断, 所以iOS10出了新的API真的是造福我们这些开发者. 不多说, 先了解新的API:
@available(iOS 10.0, *)
open class UIViewPropertyAnimator : NSObject, UIViewImplicitlyAnimating, NSCopying
@NSCopying open var timingParameters: UITimingCurveProvider? { get }
open var duration: TimeInterval { get }
open var delay: TimeInterval { get }
open var isUserInteractionEnabled: Bool
open var isManualHitTestingEnabled: Bool
open var isInterruptible: Bool
timingParameters: 时间参数
duration: 持续时间
delay: 延迟时间
isUserInteractionEnabled: 是否可交互
isManualHitTestingEnabled: 是否启动手动测试
isInterruptible: 是否可被打断
构造方法:
public init(duration: TimeInterval, timingParameters parameters: UITimingCurveProvider)
duration: 持续时间
timingParameters: 时间参数
public convenience init(duration: TimeInterval, curve: UIViewAnimationCurve, animations: (@escaping () -> Swift.Void)? = nil)
duration: 持续时间
curve: 动画曲线
animations: 动画执行闭包
public convenience init(duration: TimeInterval, controlPoint1 point1: CGPoint, controlPoint2 point2: CGPoint, animations: (@escaping () -> Swift.Void)? = nil)
duration: 持续时间
controlPoint1: 控制点1
controlPoint2: 控制点2
animations: 动画执行闭包
public convenience init(duration: TimeInterval, dampingRatio ratio: CGFloat, animations: (@escaping () -> Swift.Void)? = nil)
duration: 持续时间
dampingRatio: 减震比率
animations: 动画执行闭包
运行属性动画方法:
open class func runningPropertyAnimator(withDuration duration: TimeInterval, delay: TimeInterval, options: UIViewAnimationOptions = [], animations: @escaping () -> Swift.Void, completion: (@escaping (UIViewAnimatingPosition) -> Swift.Void)? = nil) -> Self
duration: 持续时间
options: 动画选项
animations: 动画执行闭包
completion: 动画完成闭包
添加动画组方法:
open func addAnimations(_ animation: @escaping () -> Swift.Void, delayFactor: CGFloat)
animation: 动画执行闭包
delayFactor: 延迟比率, 按照百分比计算 范围0~1
动画组完成方法:
open func addCompletion(_ completion: @escaping (UIViewAnimatingPosition) -> Swift.Void)
completion: 完成执行闭包
继续动画方法:
open func continueAnimation(withTimingParameters parameters: UITimingCurveProvider?, durationFactor: CGFloat)
withTimingParameters: 时间参数
durationFactor: 持续比率, 按照百分比计算 范围0~1
动画状态:
@available(iOS 10.0, *)
public enum UIViewAnimatingState : Int {
case inactive // The animation is not executing.
case active // The animation is executing.
case stopped // The animation has been stopped and has not transitioned to inactive.
}
动画位置:
@available(iOS 10.0, *)
public enum UIViewAnimatingPosition : Int {
case end
case start
case current
}
动画协议:
public protocol UIViewAnimating : NSObjectProtocol
@available(iOS 10.0, *)
public var state: UIViewAnimatingState { get }
public var isRunning: Bool { get }
public var isReversed: Bool { get set }
public var fractionComplete: CGFloat { get set }
public func startAnimation()
public func startAnimation(afterDelay delay: TimeInterval)
public func pauseAnimation()
public func stopAnimation(_ withoutFinishing: Bool)
@available(iOS 10.0, *)
public func finishAnimation(at finalPosition: UIViewAnimatingPosition)
state: 动画状态
isRunning: 动画是否在执行
isReversed: 动画是否反向执行
fractionComplete: 分段完成 范围0~1
startAnimation: 开始执行动画
startAnimation(afterDelay:): 延迟执行动画
pauseAnimation: 暂停动画执行
finishAnimation: 完成动画知悉在某个动画位置
二、实战实例
这次的API有点多, 因为本人也是第一次接触所以把每个都尝试了一遍, 我们就来使用这些API进行实战, 和之前一样, 我们就通过Stroyboard搭建界面 (由于Demo代码较多, 只列举具体的动画部分)

我们首先先将动画抽象到一个类中:
class AnimatorFactory {
...
}
添加缩放动画:
static func scaleUp(view: UIView) -> UIViewPropertyAnimator {
let scale = UIViewPropertyAnimator(duration: 0.33, curve: .easeIn) //属性动画初始化
scale.addAnimations { //添加动画组
view.alpha = 1.0
}
scale.addAnimations({ //添加动画组
view.transform = .identity
}, delayFactor: 0.33) //延迟33%执行
scale.addCompletion {_ in //完成后打印
print("ready")
}
return scale
}
添加摇晃动画:
@discardableResult //去除黄色警告
static func jiggle(view: UIView) -> UIViewPropertyAnimator {
return UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 0.33, delay: 0, //直接执行属性动画
animations: { UIView.animateKeyframes(withDuration: 1, delay: 0, //关键帧动画
animations: { UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.25) {
view.transform = CGAffineTransform(rotationAngle: -.pi/8)
}
UIView.addKeyframe(withRelativeStartTime: 0.25, relativeDuration: 0.75) {
view.transform = CGAffineTransform(rotationAngle: +.pi/8)
}
UIView.addKeyframe(withRelativeStartTime: 0.75, relativeDuration: 1.0) {
view.transform = .identity
}
},
completion: nil
)
},
completion: {_ in
view.transform = .identity //完成后置空
}
)
}
添加淡入淡出动画:
@discardableResult
static func fade(view: UIView, visible: Bool) -> UIViewPropertyAnimator {
return UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 0.5, delay: 0.1,
options: [.curveEaseOut],
animations: {
view.alpha = visible ? 1 : 0
}
)
}
添加约束动画:
@discardableResult
static func animateConstraint(view: UIView, constraint: NSLayoutConstraint, by: CGFloat) -> UIViewPropertyAnimator {
let spring = UISpringTimingParameters(dampingRatio: 0.55) //这个和之前的弹簧动画类似
let animator = UIViewPropertyAnimator(duration: 1.0, timingParameters: spring)
animator.addAnimations {
constraint.constant += by //约束操作
view.layoutIfNeeded() //刷帧
}
return animator
}
添加闪烁动画:
static func grow(view: UIVisualEffectView, blurView: UIVisualEffectView) -> UIViewPropertyAnimator {
// 1
view.contentView.alpha = 0
view.transform = .identity
// 2
let animator = UIViewPropertyAnimator(duration: 0.5, curve: .easeIn)
// 3
animator.addAnimations {
UIView.animateKeyframes(withDuration: 0.5, delay: 0.0, animations: {
UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 1.0) {
blurView.effect = UIBlurEffect(style: .dark)
view.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
}
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5) {
view.transform = view.transform.rotated(by: -.pi/8)
}
})
}
// 4
animator.addCompletion {position in
switch position {
case .start:
blurView.effect = nil
case .end:
blurView.effect = UIBlurEffect(style: .dark)
default: break
}
}
return animator
}
进行属性动画的调用:
@IBAction func toggleShowMore(_ sender: UIButton) {
self.showsMore = !self.showsMore
let animations = { //创建动画组闭包
self.widgetHeight.constant = self.showsMore ? 230 : 130
if let tableView = self.tableView {
tableView.beginUpdates() //进行tableView刷新动画
tableView.endUpdates()
tableView.layoutIfNeeded() //刷布局
}
}
let textTransition = { //View转场
UIView.transition(with: sender, duration: 0.25, options: .transitionCrossDissolve,
animations: {
sender.setTitle(self.showsMore ? "Show Less" : "Show More", for: .normal)
},
completion: nil
)
}
if let toggleHeightAnimator = toggleHeightAnimator, toggleHeightAnimator.isRunning {
toggleHeightAnimator.addAnimations(animations)
toggleHeightAnimator.addAnimations(textTransition, delayFactor: 0.5)
} else {
let spring = UISpringTimingParameters(mass: 30, stiffness: 1000, damping: 300, initialVelocity: CGVector.zero)
toggleHeightAnimator = UIViewPropertyAnimator(duration: 0.0, timingParameters: spring) //初始化动画
toggleHeightAnimator?.addAnimations(animations) //添加动画组
toggleHeightAnimator?.addAnimations(textTransition, delayFactor: 0.5)
toggleHeightAnimator?.startAnimation() //开始动画
}
widgetView.expanded = showsMore
widgetView.reload()
}
三、运行效果
1、运行效果

2、文件截图

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权
[Animations] 快速上手 iOS10 属性动画的更多相关文章
- 如何快速上手基础的CSS3动画
前言 说起CSS3动画,就必须说说 transform,translate,transition,animation这4个属性,transform主要定义元素的动作,比如旋转.倾斜.位移等,trans ...
- Netron开发快速上手(一):GraphControl,Shape,Connector和Connection
版权所有,引用请注明出处:<<http://www.cnblogs.com/dragon/p/5203663.html >> 本文所用示例下载FlowChart.zip 一个用 ...
- 快速上手RaphaelJS-Instant RaphaelJS Starter翻译(一)
(目前发现一些文章被盗用的情况,我们将在每篇文章前面添加原文地址,本文源地址:http://www.cnblogs.com/idealer3d/p/Instant_RaphaelJS_Start ...
- UnityShader快速上手指南(二)
简介 前一篇介绍了如果编写最基本的shader,接下来本文将会简单的深入一下,我们先来看下效果吧 呃,gif效果不好,实际效果是很平滑的动态过渡 实现思路 1.首先我们要实现一个彩色方块 2.让色彩动 ...
- android104 帧动画,补间动画,属性动画
##帧动画FrameAnimation* 多张图片快速切换,形成动画效果* 帧动画使用xml定义 package com.itheima.frameanimation; import android. ...
- 快速上手最棒的网格框架ag-Grid
由于对aggrid由衷的感谢, 又忍不住写了一篇软文来推广它(其实主要是为了弥补我把enterprise版扣下来后内心的愧疚...) ag-Grid是速度最快,功能最丰富的JavaScript dat ...
- 【转】Vue.js 2.0 快速上手精华梳理
Vue.js 2.0 快速上手精华梳理 Sandy 发掘代码技巧:公众号:daimajiqiao 自从Vue2.0发布后,Vue就成了前端领域的热门话题,github也突破了三万的star,那么对于新 ...
- CSS快速入门基础篇,让你快速上手(附带代码案例)
1.什么是CSS 学习思路 CSS是什么 怎么去用CSS(快速上手) CSS选择器(难点也是重点) 网页美化(文字,阴影,超链接,列表,渐变等) 盒子模型 浮动 定位 网页动画(特效效果) 项目格式: ...
- [Android开发学iOS系列] 快速上手UIKit
快速上手iOS UIKit UIKit是苹果官方的framework, 其中包含了各种UI组件, window和view, 事件处理, 交互, 动画, 资源管理等基础设施支持. 按照前面的介绍, 用U ...
随机推荐
- @selector 如何调用在另一个类中的静态函数?
可以在同一个类的methodName这个函数中再调用另一个类中的静态方法
- 算法:Rate of Growth
Rate of growth describes how an algorithm’s complexity changes as the input size grows. This is comm ...
- oracle直方图
直方图 当某列数据分布不均衡.为了让CBO能生成最佳的运行计划,我们可能须要对表收集直方图,直方图最大的桶数(Bucket)是254. 收集直方图是一个很耗时的过程,如无必要.千万别去收集直方图. O ...
- icanhazip.com 使你在不论什么地方知道你的公网IP地址
icanhazip.com 使你在不论什么地方知道你的公网IP地址 icanhazip.com是一个网址,你在浏览器中输入这个网址,你就能得到你的公网IP地址了. 我在Linux下一般使用curl i ...
- UTF-8,Unicode,GBK,希腊字母读法,ASCII码表,HTTP错误码,URL编码表,HTML特殊字符,汉字编码简明对照表
UNICODE,GBK,UTF-8区别 UNICODE,GBK,UTF-8区别 简单来说,unicode,gbk和大五码就是编码的值,而utf-8,uft-16之类就是这个值的表现形式.而前面那 ...
- JBoss 系列一 O O:Maven jBPM 6 集成演示样例
概述 jBPM 6 中底层架构基于 Maven,所以我们能够非常easy的进行 Maven jBPM 6 集成演示样例,本文分三个部分: 基本原理介绍 Maven jBPM 6 集成 jBPM 6 中 ...
- Python在Windows下操作CH341DLL
#! /usr/bin/env python #coding=utf-8 import os import time from ctypes import * class USBI2C(): ch34 ...
- OpenCV学习(17) 细化算法(5)
本章我们看下Pavlidis细化算法,参考资料http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/con ...
- 掌握Sed命令
带书签PDF版,喜欢的话,欢迎多提意见和建议,你的支持是血蝙蝠最大的前进动力! http://download.csdn.net/detail/challenge_c_plusplus/6480007 ...
- 国庆大礼包:2014年最全的ANDROID GUI模板和线框图免费下载
距离上次分享GUI模板有很长时间了,这段时间里设计趋势不断变化,谷歌推出了最新的Android L以及全新的界面设计,UI设计师又有得忙了,今天收集了一组实用的GUI模板和线框图,包含最新的Andro ...