之前我们介绍了PropertyAnimator,这一篇是之前文章的延伸。之前我们说过PropertyAnimator并不是针对View进行设计的动画类,而是为了解决对任意对象的指定属性值进行连续变换而出现的。而ViewPropertyAnimator出现的意义恰恰在于他是View而生的,他解决了View在使用属性动画时步骤繁琐,效率低下(使用PropertyAnimator为View设置多种动画,每种动画在执行过程中都会单独的触发View的UI重绘)的问题。
但是ViewPropertyAnimator与PropertyAnimator并不是继承关系,ViewPropertyAnimator是单独设计的类,只不过其动画实现时用到了ValueAnimator,后面我们分析源码的时候会详细说。
ViewPropertyAnimator的使用
基础使用
ViewPropertyAnimator使用起来特别简单:
view.animate().rotation(180).alpha(0.2f).translationXBy(200).setDuration(5000);
通过view.animate()
获取ViewPropertyAnimator实例,然后通过链式调用设置方法实现动画效果,甚至都不需要调用start()
方法,就可以开始动画,相比用PropertyAnimator来实现View动画要简易的多。
常用方法
设置动画时长与Interpolator:
setDuration(long duration) //设置动画时长
setInterpolator(TimeInterpolator interpolator) //设置Interpolator
设置动画监听:
setListener(Animator.AnimatorListener listener)
setUpdateListener(ValueAnimator.AnimatorUpdateListener listener)
开启硬件加速:
withLayer() //开启硬件加速,动画结束自动关闭
设置动画开始和结束的Runnable:
//提供了两个方法用于设置动画开始和结束时触发的Runnable
withStartAction(Runnable runnable)
withEndAction(Runnable runnable)
动画效果设置:
方法太多不一一列举了无非就是:透明度、旋转、位移和缩放效果。需要注意的是每种设置方法都提供了其By方法,如:
translationX(float value) //View在X轴移动相对于它父容器的左上角坐标偏移量value
translationXBy(float value) //View在X轴当前位置基础上移动value
简单来说就是,比如:view执行了一次translationX(100)
,执行完成之后再次执行translationX(100)
不会有任何效果。但是如果view执行的是translationXBy(100)
,执行完成之后再次执行translationXBy(100)
还会在当前位置的基础上在X轴上再移动100像素。
链式调用
上面提到的所有方法皆为链式调用,代码量少,逻辑清晰,便于阅读。
view.animate().rotation(180).alpha(0.2f).translationXBy(200)
.setDuration(5000).setInterpolator(new LinearInterpolator())
//开启硬件加速
.withLayer()
.withEndAction(new Runnable() {
@Override
public void run() {
//动画结束触发任务
Toast.makeText(ViewPropertyAnimatorActivity.this,"StartRunnable",Toast.LENGTH_SHORT).show();
}
})
.withStartAction(new Runnable() {
@Override
public void run() {
//动画开始触发任务
Toast.makeText(ViewPropertyAnimatorActivity.this,"StartRunnable",Toast.LENGTH_SHORT).show();
}
});
链式调用的例子我们在日常开发中有很多,比如:Glide.with(context).load(path).into(imageView);
好处就是使用简单便捷,不用初始化一个对象出来然后在调用对象的方法,可以通过一行代码实现对象的初始化和方法的调用。
那么怎么实现一个链式调用的对象呢?简单来说就是在所有链式调用方法中返回当前类对象this,来看例子:
public class Person {
private static Person mPerson;
private String name;
private int age;
private String sex;
private Person() {
}
//单例
public static Person getInstance() {
if (mPerson == null) {
mPerson = new Person();
}
return mPerson;
}
public Person setName(String name) {
this.name = name;
return this;
}
public Person setAge(int age) {
this.age = age;
return this;
}
public Person setSex(String sex) {
this.sex = sex;
return this;
}
}
定义了一个Person类使用单例模式,所有的方法都需要返回this对象,使用方式如下:
Person.getInstance().setAge(18).setSex("female").setName("Jane");