动画入门和进阶文章列表: Animation动画概述和执行原理
Android动画之补间动画TweenAnimation
Android动画之逐帧动画FrameAnimation
Android动画之插值器简介和系统默认插值器
Android动画之插值器Interpolator自定义
Android动画之视图动画的缺点和属性动画的引入
Android动画之ValueAnimator用法和自定义估值器
Android动画之ObjectAnimator实现补间动画和ObjectAnimator自定义属性
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator
Android动画之AnimatorSet联合动画用法
Android动画之LayoutTransition布局动画
Android动画之共享元素动画
Android动画之ViewPropertyAnimator(专用于view的属性动画)
Android动画之Activity切换动画overridePendingTransition实现和Theme Xml方式实现
Android动画之ActivityOptionsCompat概述
Android动画之场景变换Transition动画的使用
Android动画之Transition和TransitionManager使用
Android动画之圆形揭露动画Circular Reveal
1 AnimatorSet概述 已经讲完了ObjectAnimator的关键用法,可以利用现有的函数实现一个动画改变多个属性,多个动画一起执行类似ofPropertyValuesHolder和ObjectAnimator的ofxx函数同时写入两个属性的函数,但这些都是在一个动画中,所有的动画设置都是共用的。有时也需要能够让多个动画相互配合的运行,AnimatorSet就可以实现这个功能(其实我们也可以为每个动画设置监听,然后执行下一个动画,但是操作比较繁琐),AnimatorSet可以实现复杂的组合动画,既可以同时对多个对象做动画并控制执行顺序,也可以控制单个对象的动画执行顺序。
Android Developer :https://developer.android.google.cn/reference/android/animation/AnimatorSet
AnimatorSet可以指定一组动画的执行顺序,让它们可以一起执行,顺序执行,延迟执行。1.1 AnimatorSet的生成: 代码直接利用 AnimatorSet()
如果是XML定义AnimatorSet 利用 AnimatorInflater.loadAnimator()加载(使用较少)
AnimatorSet可以作用于ObjectAnimator和ValueAnimator,但通常ObjectAnimator用的比较多。
1.2 AnimatorSet和ObjectAnimator中重叠的函数,谁生效? 查看AnimatorSet的方法,发现了几个和Animator动画相同的设置属性的方法,那么这些方法和内部单个动画同时设置谁生效呢?
setDuration (long duration):设置每个内部子动画的时长,默认每个子动画使用自己默认的时长,如果AnimatorSet设置了时长,子动画将继承这个时长,而子动画自己设置的duration将失效。
下面会列举其他方法,和setDuration方法类似,都是如果没有设置就使用子动画自己的,如果AnimatorSet设置了就使用AnimatorSet设置的属性。
setInterpolator (TimeInterpolator interpolator),设置之后内部子动画的插值器都是这个
setTarget(Object target),设置之后所有内部子动画都作用于相同的target目标对象
特例:比较简单就不用代码说明了
setStartDelay(long startDelay)函数是个特例,它不会覆盖子动画开始延迟,只对AnimatorSet的开始时间起作用,所以它会延后AnimatorSet激活整体动画的开始时间。
1.3 两种添加动画到AnimatorSet的方法
- 一种是利用playTogether()或者playSequentially(),可以一次添加所有的动画到AnimatorSet中,
- 一种是利用play(Animator)构建Builder对象,然后利用Builder提供的方法,一个一个的添加动画,并设置各个动画间执行顺序的依赖关系
end() 结束动画,会结束AnimatorSet中的所有子动画。
getChildAnimations() 获取所有受AnimatorSet控制的动画
isStarted(),AnimationSet动画是否开始了,true开始
isRunning(),AnimationSet开始之后(isStarted = true),内部是否有子动画正在执行,有动画执行返回true
pause()暂停动画,
resume()恢复暂停的动画
play(Animator anim)获取Builder对象
2 playTogether和playSequentially 2.1 playTogether 多个动画同时执行,可以是对一个对象执行的多个动画,也可以是对多个对象的多个动画。
playTogether(Collection items) //利用集合添加动画
playTogether(Animator… items) //利用可变参数添加动画
多个动画作用于一个对象
ObjectAnimator objectAnimator1 = ObjectAnimator.ofArgb(mTextView, "backgroundColor", Color.WHITE, Color.GREEN);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mTextView, "scaleX", 0.1f, 1.2f);
ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(mTextView, "scaleY", 0.5f, 1.0f);
ObjectAnimator objectAnimator4 = ObjectAnimator.ofFloat(mTextView, "translationY", 0, 250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4);
animatorSet.setDuration(3000);
animatorSet.start();
文章图片
如果多个动画同时对一个属性进行操作,会发生错误吗?
不会发生错误,会正常执行,只不过会按照playTogether添加的最后一个动画覆盖前面操作相同属性的动画,也可能没有覆盖,但确实是最后一个添加的动画起了作用。
ObjectAnimator objectAnimator1 = ObjectAnimator.ofArgb(mTextView, "backgroundColor", Color.WHITE, Color.GREEN);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mTextView, "scaleX", 0.1f, 1.2f);
ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(mTextView, "scaleY", 0.5f, 1.0f);
ObjectAnimator objectAnimator4 = ObjectAnimator.ofFloat(mTextView, "translationY", 0, 250);
ObjectAnimator objectAnimator5 = ObjectAnimator.ofFloat(mTextView, "translationY", 200, 450);
ObjectAnimator objectAnimator6 = ObjectAnimator.ofFloat(mTextView, "translationY", 300, 600);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4,objectAnimator5,objectAnimator6);
animatorSet.setDuration(3000);
animatorSet.start();
animatorSet.playTogether(objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4,objectAnimator5,objectAnimator6);
最终会按照objectAnimator6的效果进行展示。
文章图片
animatorSet.playTogether(objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator6,objectAnimator5,objectAnimator4);
最终会按照objectAnimator4的效果进行展示。
文章图片
多个动画作用于多个对象
ObjectAnimator objectAnimator1 = ObjectAnimator.ofArgb(mTextView, "backgroundColor", Color.WHITE, Color.GREEN);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mTextView, "scaleX", 0.1f, 1.2f);
ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(mTextView, "scaleY", 0.5f, 1.0f);
ObjectAnimator objectAnimator4 = ObjectAnimator.ofFloat(mTextView, "translationY", 0, 250);
ObjectAnimator objectAnimator7 = ObjectAnimator.ofArgb(mTextView2, "backgroundColor", Color.WHITE, Color.GREEN);
ObjectAnimator objectAnimator8 = ObjectAnimator.ofFloat(mTextView2, "scaleX", 0.1f, 1.2f);
ObjectAnimator objectAnimator9 = ObjectAnimator.ofFloat(mTextView2, "scaleY", 0.5f, 1.0f);
ObjectAnimator objectAnimator10 = ObjectAnimator.ofFloat(mTextView2, "translationY", 0, 250);
ObjectAnimator objectAnimator11 = ObjectAnimator.ofArgb(mTextView3, "backgroundColor", Color.WHITE, Color.GREEN);
ObjectAnimator objectAnimator12 = ObjectAnimator.ofFloat(mTextView3, "scaleX", 0.1f, 1.2f);
ObjectAnimator objectAnimator13 = ObjectAnimator.ofFloat(mTextView3, "scaleY", 0.5f, 1.0f);
ObjectAnimator objectAnimator14 = ObjectAnimator.ofFloat(mTextView3, "translationY", 0, 250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4
,objectAnimator7,objectAnimator8,objectAnimator9,objectAnimator10,objectAnimator11,objectAnimator12,objectAnimator13,objectAnimator14);
animatorSet.setDuration(3000);
animatorSet.start();
文章图片
2.2 playSequentially 顺序播放动画:
playSequentially(List items)
playSequentially(Animator… items)
对于playSequentially作用于单个和多个对象的区别和playTogether一样,所以这里只讲解playSequentially作用于多个对象。【android动画系列|Android动画之AnimatorSet联合动画用法】上面的代码修改为playSequentially,并且把时间修改为1000,否则每个动画顺序执行3s会很耗时间。
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4
,objectAnimator7,objectAnimator8,objectAnimator9,objectAnimator10,objectAnimator11,objectAnimator12,objectAnimator13,objectAnimator14);
animatorSet.setDuration(1000);
animatorSet.start();
文章图片
注意:如何实现动画的循环播放
- playTogether和playSequentially只负责激活控件动画,后续的动画还是由ObjectAnimator自己控制。
- playSequentially是一个动画执行完后执行下一个动画,但如果前一个动画是无限循环,下一个动画永远不会执行。
AnimatorSet中没有设置动画执行次数的函数,所以无法利用AnimatorSet设置动画循环播放, playSequentially一个动画执行完后执行另外一个动画,如果前一个动画是无限循环,后一个动画不会执行,所以也无法实现循环播放动画,所以只能利用playTogether播放动画时每个动画设置无线循环:
ObjectAnimator objectAnimator5 = ObjectAnimator.ofFloat(mTextView, "translationY", 200, 450);
ObjectAnimator objectAnimator6 = ObjectAnimator.ofFloat(mTextView, "translationY", 300, 600);
ObjectAnimator objectAnimator1 = ObjectAnimator.ofArgb(mTextView, "backgroundColor", Color.WHITE, Color.GREEN);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mTextView, "scaleX", 0.1f, 1.2f);
ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(mTextView, "scaleY", 0.5f, 1.0f);
ObjectAnimator objectAnimator4 = ObjectAnimator.ofFloat(mTextView, "translationY", 0, 250);
ObjectAnimator objectAnimator7 = ObjectAnimator.ofArgb(mTextView2, "backgroundColor", Color.WHITE, Color.GREEN);
ObjectAnimator objectAnimator8 = ObjectAnimator.ofFloat(mTextView2, "scaleX", 0.1f, 1.2f);
ObjectAnimator objectAnimator9 = ObjectAnimator.ofFloat(mTextView2, "scaleY", 0.5f, 1.0f);
ObjectAnimator objectAnimator10 = ObjectAnimator.ofFloat(mTextView2, "translationY", 0, 250);
ObjectAnimator objectAnimator11 = ObjectAnimator.ofArgb(mTextView3, "backgroundColor", Color.WHITE, Color.GREEN);
ObjectAnimator objectAnimator12 = ObjectAnimator.ofFloat(mTextView3, "scaleX", 0.1f, 1.2f);
ObjectAnimator objectAnimator13 = ObjectAnimator.ofFloat(mTextView3, "scaleY", 0.5f, 1.0f);
ObjectAnimator objectAnimator14 = ObjectAnimator.ofFloat(mTextView3, "translationY", 0, 250);
objectAnimator1.setRepeatCount(-1);
objectAnimator2.setRepeatCount(-1);
objectAnimator3.setRepeatCount(-1);
objectAnimator4.setRepeatCount(-1);
objectAnimator5.setRepeatCount(-1);
objectAnimator6.setRepeatCount(-1);
objectAnimator7.setRepeatCount(-1);
objectAnimator8.setRepeatCount(-1);
objectAnimator9.setRepeatCount(-1);
objectAnimator10.setRepeatCount(-1);
objectAnimator11.setRepeatCount(-1);
objectAnimator12.setRepeatCount(-1);
objectAnimator13.setRepeatCount(-1);
objectAnimator14.setRepeatCount(-1);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4
,objectAnimator7,objectAnimator8,objectAnimator9,objectAnimator10,objectAnimator11,objectAnimator12,objectAnimator13,objectAnimator14);
//animatorSet.play()
animatorSet.setDuration(3000);
animatorSet.start();
文章图片
如果利用playSequentially并且前一个动画是循环动画:
文章图片
所以最终实现循环动画的方法为,每个内部子动画设置为无限循环
3 利用play(Animator)构建Builder对象 Builder play(Animator anim);生成builder对象,Builder能够控制动画的执行顺序和相互之间的依赖。
通过AnimatorSet中的play方法可以获取AnimatorSet.Builder对象,通过Builder内部的函数添加动画到AnimatorSet中,后续的所有动画都是以play传入的动画为标准进行相应操作(后面会详细讲述)。
Builder的函数: public Builder with(Animator anim) 和前面动画一起执行
public Builder before(Animator anim) 执行前面的动画后再执行该动画
public Builder after(Animator anim) 先执行这个动画再执行前面动画
public Builder after(long delay) 延迟n毫秒之后执行动画
public Builder with(Animator anim) 和前面动画一起执行: 例子还用上面的动画,三个view同时执行变色动画:
ObjectAnimator objectAnimator1 = ObjectAnimator.ofArgb(mTextView, "backgroundColor", Color.WHITE, Color.GREEN);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mTextView, "scaleX", 0.1f, 1.2f);
ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(mTextView, "scaleY", 0.5f, 1.0f);
ObjectAnimator objectAnimator4 = ObjectAnimator.ofFloat(mTextView, "translationY", 0, 250);
ObjectAnimator objectAnimator7 = ObjectAnimator.ofArgb(mTextView2, "backgroundColor", Color.WHITE, Color.GREEN);
ObjectAnimator objectAnimator8 = ObjectAnimator.ofFloat(mTextView2, "scaleX", 0.1f, 1.2f);
ObjectAnimator objectAnimator9 = ObjectAnimator.ofFloat(mTextView2, "scaleY", 0.5f, 1.0f);
ObjectAnimator objectAnimator10 = ObjectAnimator.ofFloat(mTextView2, "translationY", 0, 250);
ObjectAnimator objectAnimator11 = ObjectAnimator.ofArgb(mTextView3, "backgroundColor", Color.WHITE, Color.GREEN);
ObjectAnimator objectAnimator12 = ObjectAnimator.ofFloat(mTextView3, "scaleX", 0.1f, 1.2f);
ObjectAnimator objectAnimator13 = ObjectAnimator.ofFloat(mTextView3, "scaleY", 0.5f, 1.0f);
ObjectAnimator objectAnimator14 = ObjectAnimator.ofFloat(mTextView3, "translationY", 0, 250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(objectAnimator1).with(objectAnimator7).with(objectAnimator11);
animatorSet.setDuration(3000);
animatorSet.start();
动画objectAnimator1作用于第一个view,objectAnimator7作用于第二个view,objectAnimator11作用于第三个view。
文章图片
public Builder before(Animator anim) 执行前面的动画后再执行该动画: 第一个view先执行变色操作再执行X轴缩放操作:
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(objectAnimator1).before(objectAnimator2);
animatorSet.setDuration(3000);
animatorSet.start();
文章图片
public Builder after(Animator anim) 先执行这个动画再执行前面动画: 第一个view先执行X轴缩放动画,再执行变色操作。
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(objectAnimator1).after(objectAnimator2);
animatorSet.setDuration(3000);
animatorSet.start();
文章图片
public Builder after(long delay) 延迟n毫秒之后执行动画 AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(objectAnimator1).after(objectAnimator2).after(10000);
animatorSet.setDuration(3000);
animatorSet.start();
如果设置过after延迟执行之后设置setDuration,after延迟会被duration的时间覆盖,不会产生延迟,而且延迟是对play函数中的动画来说的,调用了after(非延迟)之后,after(非延迟)中的动画是不受after延迟时间影响的。
animatorSet.play(objectAnimator1).after(objectAnimator2).after(10000);
// animatorSet.setDuration(3000);
animatorSet.start();
文章图片
4 AnimatorSet Builder的操作方式,每次play,或者链式操作
AnimatorSet 的play函数和Builder的with,before,after函数都返回Builder 对象实例,所以我们可每次通过play获取Builder进行动画操作,也可以利用Builder函数返回Builder对象的特性进行链式操作,两种操作方式有什么不同呢?重要:
先看AnimatorSet的play方法产生的Builder对象:
* Note that play()
is the only way to tell the
* Builder
the animation upon which the dependency is created,
* so successive calls to the various functions in Builder
* will all refer to the initial parameter supplied in play()
* as the dependency of the other animations. For example, calling
* play(a1).before(a2).before(a3)
will play both a2
* and a3
when a1 ends;
it does not set up a dependency between
* a2
and a3
.
public Builder play(Animator anim) {
if (anim != null) {
return new Builder(anim);
}
return null;
}
每次调用play方法都会产生一个新的Builder对象,这个对象约束内部动画的执行顺序。而且重要的一点是play()方法是唯一一种获取Builder对象的方式,后续所有的动画执行都以play方法中传入的动画为基准,例如:
AnimatorSet s = new AnimatorSet();
s.play(anim1).with(anim2);
s.play(anim2).before(anim3);
s.play(anim4).after(anim3);
动画anim1 和anim2有关系,anim2和anim3有关系,anim3和anim4有关系。anim1和anim2将同时执行,anim2先于anim3执行,anim3 先于anim4执行,所以最终的执行顺序为anim1和anim2同时开始执行,anim2执行完后开始执行anim3,anim3执行完后开始执行anim4.
代码示例:
animatorSet.play(objectAnimator1).before(objectAnimator2);
animatorSet.play(objectAnimator1).with(objectAnimator7);
animatorSet.play(objectAnimator7).after(objectAnimator11);
animatorSet.setDuration(3000);
animatorSet.start();
结果:动画会先执行objectAnimator11(gif中的第三个view变背景),然后objectAnimator1(gif中的第一个view变背景)和objectAnimator7(第二个view变背景)同时执行,最后执行objectAnimator2(缩放);
文章图片
Builder with before after 函数返回Builder对象,链式操作动画
/**
* Sets up the given animation to play at the same time as the animation supplied in the
* {@link AnimatorSet#play(Animator)} call that created this Builder
object.
*
* @param anim The animation that will play when the animation supplied to the
* {@link AnimatorSet#play(Animator)} method starts.
*/
public Builder with(Animator anim) {
Node node = getNodeForAnimation(anim);
mCurrentNode.addSibling(node);
return this;
}/**
* Sets up the given animation to play when the animation supplied in the
* {@link AnimatorSet#play(Animator)} call that created this Builder
object
* ends.
*
* @param anim The animation that will play when the animation supplied to the
* {@link AnimatorSet#play(Animator)} method ends.
*/
public Builder before(Animator anim) {
Node node = getNodeForAnimation(anim);
mCurrentNode.addChild(node);
return this;
}/**
* Sets up the given animation to play when the animation supplied in the
* {@link AnimatorSet#play(Animator)} call that created this Builder
object
* to start when the animation supplied in this method call ends.
*
* @param anim The animation whose end will cause the animation supplied to the
* {@link AnimatorSet#play(Animator)} method to play.
*/
public Builder after(Animator anim) {
Node node = getNodeForAnimation(anim);
mCurrentNode.addParent(node);
return this;
}
play之后的链式调用不会产生新的Builder对象,会把传入的动画添加到play函数产生的Builder对象的node列表中等待执行。代码示例看下面:
所以with before after 函数被调用之后链式操作动画是操作同一个Builder对象内部的Node链,所以都是以play函数传入的动画为基准。
play(a1).before(a2).before(a3) a2,a3动画都是以a1动画为基准,a1动画执行结束之后a2,a3将同时执行,a1动画和a2,a3有关系,但是a2,a3之间是没有关系的。
5 Builder链式调用的一些举例 上面提到调用play函数后后续的所有动画都是以play传入的动画为标准进行相应操作
下面我们通过几个列子来说明:
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(objectAnimator1).before(objectAnimator2).before(objectAnimator3).before(objectAnimator4).with(objectAnimator7).with(objectAnimator11);
animatorSet.setDuration(3000);
animatorSet.start();
其中objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4 操作左边第一个view。
objectAnimator7操作第二个view,
objectAnimator11操作第三个view。
最终的结果为三个view同时开始动画也就是objectAnimator1,objectAnimator7,objectAnimator11同时开始执行,objectAnimator1执行完之后objectAnimator2,objectAnimator3,objectAnimator4同时开始执行。:
文章图片
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(objectAnimator1).before(objectAnimator2).before(objectAnimator3).before(objectAnimator4).with(objectAnimator7).with(objectAnimator11).after(objectAnimator12);
animatorSet.setDuration(3000);
animatorSet.start();
其中objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4 操作左边第一个view。
objectAnimator7操作第二个view,
objectAnimator11,objectAnimator12操作第三个view。
结果:objectAnimator12先执行动画,接着objectAnimator1,objectAnimator7,objectAnimator11动画会同时执行,objectAnimator1执行完之后objectAnimator2,objectAnimator3,objectAnimator4动画会同时执行。
文章图片
animatorSet.play(objectAnimator1).before(objectAnimator2).after(objectAnimator4).before(objectAnimator3).after(objectAnimator14).after(objectAnimator11);
animatorSet.setDuration(3000);
animatorSet.start();
其中objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4 操作左边第一个view。
objectAnimator7操作第二个view,
objectAnimator11,objectAnimator12操作第三个view。
上面的代码会同时执行objectAnimator4,objectAnimator11,objectAnimator14,然后执行objectAnimator1,再执行objectAnimator2 和objectAnimator3
文章图片
链式调用动画执行顺序总结如下:6 AnimatorSet动画监听
Builder链式调用中会先执行after函数中的动画(有多个同时执行),然后执行play和with函数(有多个同时执行)中的动画,最后执行before函数中的动画(有多个同时执行)
//如果不想实现那么多方法,可以利用AnimatorListenerAdapter代替AnimatorListener
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {}@Override
public void onAnimationEnd(Animator animation) {}@Override
public void onAnimationCancel(Animator animation) {}@Override
public void onAnimationRepeat(Animator animation) {}
});
//需要api19
animatorSet.addPauseListener(new Animator.AnimatorPauseListener() {
@Override
public void onAnimationPause(Animator animation) {}@Override
public void onAnimationResume(Animator animation) {}
});
由于内部主要使用ObjectAnimator所以动画监听显得不那么重要。
7 AnimationSet xml 文件实现 用法不多,只举个例子(来自developer):
:ordering="sequentially">
>
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.animator.property_animator);
set.setTarget(myObject);
set.start();
推荐阅读
- android动画系列|Android动画之ValueAnimator用法和自定义估值器
- android动画系列|Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator
- Android动画篇(三)—— 属性动画ValueAnimator的使用
- Android动画系列|Android动画篇(五)—— 属性动画ObjectAnimator基本使用
- Android动画篇(六)—— 组合动画AnimatorSet和PropertyValuesHolder的使用
- Android动画系列|Android动画篇(二)—— 代码实现alpha、scale、translate、rotate、set及插值器动画
- 动画七、动画的PropertyValuesHolder与Keyframe
- Android动画篇(四)—— 属性动画ValueAnimator的高级进阶