属性动画是 Android API level 11(Android 3.0)中添加的动画框架,功能强大,扩展性强。介绍属性动画,就需要说明三个问题:
属性是什么?
用官方的话说,Property is a field in an object。更进一步解释,这里的属性是指一个对象中具有 setter/getter 方法的变量。
属性动画可以做什么?
一般来说,动画是一种视觉效果,但是属性动画的内容要更广泛,除了做一些视觉效果之外,属性动画还可以用类似动画的方式默默改变一些数据。当然,最主要的还是实现视觉效果,包括常见的透明度、缩放、平移、旋转效果,也可以扩展出其他的属性(比如颜色)。
与之前的 View Animation 有什么区别?
View Animation 是在 API level 1 开始支持的动画框架,内容只有基本的透明度、缩放、平移、旋转,且动画的对象只能是 View。
二者的区别有以下几点:
属性动画中新添加的类主要是这些:
作为属性动画的基类,Animator 提供了动画最基本的属性。
仅列出一部分(我觉得)常用的。
Method Name | Function |
---|---|
|
开始播放 |
|
取消动画 |
|
是否正在播放 |
addListener | 添加监听回调 |
setTarget | 设置动画目标Object |
setDuration | 设置播放时长,单位:毫秒 |
setInterpolator | 设置插值器 |
关于插值器的内容本文暂不介绍了。
构造方法
- //直接创建
- 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 | 设置重复播放次数 |
构造方法
- //直接创建
- ObjectAnimator objectAnimator = new ObjectAnimator();
- //带参数创建
- ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mView, "alpha", 1.0f, 0.7f);
- //...类似的构造方法有很多,就是参数不同,这些参数都可以通过setter方法设置。
ObjectAnimatior 增加了属性动画最基本的方法——设置属性。
Method Name | Function |
---|---|
setProperty | 设置动画目标属性 |
setPropertyName | 通过name设置动画目标属性 |
|
设置一系列动画参数,按顺序执行 |
|
设置一系列动画参数,按顺序执行 |
|
设置一系列动画参数,按顺序执行 |
AnimatorSet 的功能就是把多个各种 Animator 对象整合成一个动画,有点类似与 ViewGroup。
Method Name | Function |
---|---|
playTogether | 多个动画一起播放 |
playSequentially | 多个动画顺序播放 |
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();
- }
- });
在
方法中把变化后的颜色刷新到 UI 界面就行了。效果是这样的:
- onAnimationUpdate
相比之下 ObjectAnimator 才是属性动画中的主角,创建 ObjectAnimator 对象实现动画需要有几个要素:
属性名接受一个 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();
代码含义比较清晰,需要注意的是
默认的插值器并不是线性的,下面给出两种效果,左侧是 LinearInterpolator ,右侧是默认的。
- setInterpolator
xml 实现动画是一种比较合理的复用动画方式,可以有效避免在 Controller 层写过多只属于 View 层的代码。
属性动画的 xml 文件需要放在
文件夹下。
- res/animator
语法与 View Animation 差别比较大,大概是这样子的:
直观感受就是比 View Animation 的 xml 实现麻烦很多,实际上由于 xml 文件的限制二者功能上差不多,应该是 View Animation 更加常用一点。(个人感受)
ObjectAnimator 的代码写起来不怎么好看,因为总是在 objectAnimator.xxx(),比起单独在Activity中实现某些交互效果,把简单而常用的动画效果封装成工具类会更理想一些。但是交互效果是千变万化的,总有一些独特的动画无法复用。
于是在 API level 12 中,出现了针对 View 的属性动画 ViewPropertyAnimtor。ViewProperty 中封装了 View 相关的常用动画参数的设置以及多种回调,并用 ObjectAnimator 实现了动画效果,对外提供了相当简单易懂的流式 API,使动画的代码也可以写的很爽。
使用方法:
- 获取 ViewPropertyAnimator 对象
ViewPropertyAnimator 没有 public 的构造方法,只能通过 View 对象的
方法获得。使用的 View 对象就是动画的 target。
- animate()
ViewPropertyAnimator 对象是会重复使用的,多次调用'animate()'只会创建一个 ViewPropertyAnimator。
- 设置动画参数
相关的 API 名称都很明确,就不一一介绍效果了
- 设置回调(可选)
就是
方法。其实所有的动画都可以设置 Listener ,只是在 ViewPropertyAnimator 中更加重要,因为从 API 可以看出每一种动画只能传入一个参数,如果需要同一种动画多段执行,就只能通过监听动画结束修改参数值再开始动画。
- setListener
方法接收一个 Animator.AnimatorListener 接口的实例,可以直接创建 Animator.AnimatorListener 实例实现所有方法,也可以创建 AnimatorListenerAdapter 只重写需要的方法。
- setListener
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()
因为我并没有做过太多的动画效果,刚开始写的时候只想总结一下各种方法的用法和效果,然而那样就会不能避免的翻译官方文档,且内容杂乱,不易整理 demo。于是先写了一些简单的动画效果,依据实际代码反向整理了这篇文章。
文中 gif 图对应代码都在示例工程(AnimatorSample)中,地址:https://github.com/xhd-Git/Samples
来源: https://juejin.im/post/5a2567b46fb9a045030fed5e