000 属性动画简介
属性动画是 Android API level 11(Android 3.0)中添加的动画框架,功能强大,扩展性强。介绍属性动画,就需要说明三个问题:
属性是什么?
用官方的话说,Property is a field in an object。更进一步解释,这里的属性是指一个对象中具有 setter/getter 方法的变量。
属性动画可以做什么?
一般来说,动画是一种视觉效果,但是属性动画的内容要更广泛,除了做一些视觉效果之外,属性动画还可以用类似动画的方式默默改变一些数据。当然,最主要的还是实现视觉效果,包括常见的透明度、缩放、平移、旋转效果,也可以扩展出其他的属性(比如颜色)。
与之前的 View Animation 有什么区别?
View Animation 是在 API level 1 开始支持的动画框架,内容只有基本的透明度、缩放、平移、旋转,且动画的对象只能是 View。
二者的区别有以下几点:
- 属性动画实际改变了动画目标的属性值,比如平移一个 View,View 的位置真实发生了改变,而 View Animation仅是改变了屏幕绘制位置,真实位置不变。
- 属性动画可以作用于没有绘制到屏幕上的对象。
- 属性动画可以作用于非 View 对象,也可以制作四类基本动画之外的动画效果。
- View Animation 的代码量更少,效率更高。
001 相关API说明
属性动画中新添加的类主要是这些:
Animator
作为属性动画的基类,Animator 提供了动画最基本的属性。
仅列出一部分(我觉得)常用的。
Method Name | Function |
---|---|
start() |
开始播放 |
cancel() |
取消动画 |
isRunning() |
是否正在播放 |
addListener | 添加监听回调 |
setTarget | 设置动画目标Object |
setDuration | 设置播放时长,单位:毫秒 |
setInterpolator | 设置插值器 |
关于插值器的内容本文暂不介绍了。
ValueAnimator
构造方法
//直接创建
ValueAnimator valueAnimator = new ValueAnimator();
//带参数创建
ValueAnimator valueAnimator = ValueAnimator.ofFloat(1.0f, 2.0f);
// ValueAnimator valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), Color.RED, Color.GREEN);
// ...还有ofArgb,ofInt,ofPropertyValuesHolder
比起 Animator 增加的一些常用方法
Method Name | Function |
---|---|
setStartDelay | 设置动画启动延迟,单位:毫秒 |
addUpdateListener | 添加Value更新的监听回调 |
setRepeatMode | 设置重复播放模式,RESTART或REVERSE |
setRepeatCount | 设置重复播放次数 |
ObjectAnimtor
构造方法
//直接创建
ObjectAnimator objectAnimator = new ObjectAnimator();
//带参数创建
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mView, "alpha", 1.0f, 0.7f);
//...类似的构造方法有很多,就是参数不同,这些参数都可以通过setter方法设置。
ObjectAnimatior 增加了属性动画最基本的方法——设置属性。
Method Name | Function |
---|---|
setProperty | 设置动画目标属性 |
setPropertyName | 通过name设置动画目标属性 |
setIntValues(int... values) |
设置一系列动画参数,按顺序执行 |
setFloatValues(float... values) |
设置一系列动画参数,按顺序执行 |
setObjectValues(Object... values) |
设置一系列动画参数,按顺序执行 |
AnimatorSet
AnimatorSet 的功能就是把多个各种 Animator 对象整合成一个动画,有点类似与 ViewGroup。
Method Name | Function |
---|---|
playTogether | 多个动画一起播放 |
playSequentially | 多个动画顺序播放 |
010 使用场景分析
Animator对象
ValueAnimator 的功能很单一,比较像“时间轴”,就是设置一个值,在一段时间内以某种规则变化。这也是
ObjectAnimator 实现动画的基础。
举个例子,通过 VlaueAnimator 改变 View 的颜色:
private int mColor = Color.RED;
public ValueAnimator valueAnimator;
//...
//...
valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), mColor, Color.rgb(0,0,255));
valueAnimator.setDuration(3000);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mColor = (int) animation.getAnimatedValue();
}
});
在 onAnimationUpdate
方法中把变化后的颜色刷新到 UI 界面就行了。效果是这样的:
相比之下 ObjectAnimator 才是属性动画中的主角,创建 ObjectAnimator 对象实现动画需要有几个要素:
- propertyName:要变化的属性名(String)
- target:具有该属性的 Object 对象
- values:对应属性的变化值,数据类型要和属性的类型一致
属性名接受一个 String 类型的参数,就很容易出错。可以通过输入 target 的 object 对象,在代码提示中找 setter 方法来确定属性名。View 的属性名是比较常用的,比如:
alpha
,rotation
,scaleX
,scaleY
,translationX
,translationY
,rotationX
,rotationY
等。
举个例子,网络加载中可能会大量用到的一种loading动画。
ObjectAnimator animator = new ObjectAnimator();
animator.setPropertyName("rotation");
animator.setTarget(ivLoading);
animator.setFloatValues(0,360);
animator.setDuration(900);
animator.setRepeatMode(ObjectAnimator.RESTART);
animator.setRepeatCount(ObjectAnimator.INFINITE);
animator.setInterpolator(new LinearInterpolator());
animator.start();
代码含义比较清晰,需要注意的是setInterpolator
默认的插值器并不是线性的,下面给出两种效果,左侧是 LinearInterpolator ,右侧是默认的。
xml实现
xml 实现动画是一种比较合理的复用动画方式,可以有效避免在 Controller 层写过多只属于 View 层的代码。
属性动画的 xml 文件需要放在res/animator
文件夹下。
语法与 View Animation 差别比较大,大概是这样子的:
直观感受就是比 View Animation 的 xml 实现麻烦很多,实际上由于 xml 文件的限制二者功能上差不多,应该是 View Animation 更加常用一点。(个人感受)
view.animate()
ObjectAnimator 的代码写起来不怎么好看,因为总是在 objectAnimator.xxx(),比起单独在Activity中实现某些交互效果,把简单而常用的动画效果封装成工具类会更理想一些。但是交互效果是千变万化的,总有一些独特的动画无法复用。
于是在 API level 12 中,出现了针对 View 的属性动画 ViewPropertyAnimtor。ViewProperty 中封装了 View 相关的常用动画参数的设置以及多种回调,并用 ObjectAnimator 实现了动画效果,对外提供了相当简单易懂的流式 API,使动画的代码也可以写的很爽。
使用方法:
- 获取 ViewPropertyAnimator 对象
ViewPropertyAnimator 没有 public 的构造方法,只能通过 View 对象的 animate()
方法获得。使用的 View 对象就是动画的 target。
ViewPropertyAnimator 对象是会重复使用的,多次调用'animate()'只会创建一个 ViewPropertyAnimator。
- 设置动画参数
相关的 API 名称都很明确,就不一一介绍效果了
- 设置回调(可选)
就是setListener
方法。其实所有的动画都可以设置
Listener ,只是在 ViewPropertyAnimator 中更加重要,因为从 API 可以看出每一种动画只能传入一个参数,如果需要同一种动画多段执行,就只能通过监听动画结束修改参数值再开始动画。
setListener
方法接收一个 Animator.AnimatorListener 接口的实例,可以直接创建 Animator.AnimatorListener 实例实现所有方法,也可以创建 AnimatorListenerAdapter 只重写需要的方法。
ViewPropertyAnimator 的复用同样会影响 Listener,如果是同一个 View 的多个动画且不相关,需要在不需要 Listener 的动画中调用setListener(null)
。
这里也应该举个例子,不过没什么好的想法,姑且再写一遍
loading 动画,就当对比一下两种 API 格式吧。(kotlin代码,对比一下设置动画的 API 就好了)
ivLoadingRight.setOnClickListener {
ivLoadingRight.animate()
.rotationBy(360f)
.setDuration(800)
.setInterpolator(LinearInterpolator())
.setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator?) {
super.onAnimationEnd(animation)
ivLoadingRight.animate()
.rotationBy(360f)
.setDuration(800)
.setInterpolator(LinearInterpolator())
.start()
}
}).start()
011 结语
因为我并没有做过太多的动画效果,刚开始写的时候只想总结一下各种方法的用法和效果,然而那样就会不能避免的翻译官方文档,且内容杂乱,不易整理 demo。于是先写了一些简单的动画效果,依据实际代码反向整理了这篇文章。
文中 gif 图对应代码都在示例工程(AnimatorSample)中,地址:https://github.com/xhd-Git/Samples