上一篇我门实现了最简单的View Animatioin,能够做到缩放、移动、渐变、旋转,但是,其最大的缺点就是不能交互,只是单纯的改变了显示的位置,并不能进行交互,所以,google又引进了属性动画。
本文的所有代码:点击打开链接
一、属性动画的实现方式
属性动画,顾名思义,这种动画的本质就是修改某个对象的某个或多个属性,从而实现动画的效果。由于修改的是属性,而不是简单的显示,所以可以进行各种交互。从而我们也就知道了这种动画使用时肯定要指定要修改的属性是哪一个,该属性是如何变化,由于要修改这个属性,那么必须要为该属性提供get和set方法。
1、应用属性动画的2种方法
此处只用简单的位移动画做讲解。
(1)利用xml定义属性动画
原理很简单,和定义View Animation类似,先在res文件夹下新建一个animator目录,然后在目录下新建一个动画文件如 translate.xml,如下所示
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="3000"
android:propertyName="translationX"
android:valueFrom="0"
android:valueTo="300"
android:valueType="floatType"
/>
</set>
首先默认生成的是一个set节点,表明这个文件可以定义一个动画集合,也可以直接用<objectAnimator/>做根节点,这样只能设置一个动画效果,和set节点中只放置一个<objectAnimator>等价,这个不影响,其中propertyName就是指明我们要控制什么属性,
valueFrom和valueTo指明该属性的变化范围,valueTo必须设置,valueFrom默认为当前值,valueType指明该属性的值类型。详细的建议查看官方文档,那里有详细解释。
定义好动画文件后就是使用他,也很简单如下
Animator translateAnimator = AnimatorInflater.loadAnimator(AnimationActivity.this, R.animator.translate);
translateAnimator.setTarget(view);
translateAnimator.start();
首先自然是利用AnimatorInflater.loadAnimator来加载这个动画文件,然后利用setTarget来设置这个动画的作用对象,最后用start来启动动画。
(2)直接利用代码定义
ObjectAnimator a3 = ObjectAnimator.ofFloat(view, "translationX", 360);
a3.setDuration(2000);
a3.start();
OK,我们来分析以下,其实很简单,利用ObjectAnimator中的静态方法ofFloat等方法实例化一个动画对象,至于到底用ofFloat还是ofInt,这个取决与你控制的属性值是什么类型,然后设置时间,最后调用start方法开始播放就行了。
2、组合动画的使用
(1)利用PropertyValuesHolder实现
如果想同时修改某个对象的多个属性,就要用PropertyValuesHolder,如下
PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("rotation", 350);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2);
animator.setDuration(3000);
animator.start();
这里同时修改了view的两个属性,translationX和rotation,然后利用这两个propertyValuesHolder实例化一个动画对象,然后设置播放时间并播放就可以了。
(2)利用AnimatorSet实现
上面是利用一个Animator对象实现了修改多个属性,但是,我们也可以用多个Animator实现这个效果,如下
AnimatorSet animatorSetCode = new AnimatorSet();
ObjectAnimator a1 = ObjectAnimator.ofFloat(view, "translationX", 300);
a1.setDuration(2000);
ObjectAnimator a2 = ObjectAnimator.ofFloat(view, "rotation", 0, 187);
a2.setDuration(2000);
animatorSetCode.playSequentially(a1, a2); //按添加的顺序播放
animatorSetCode.start();
这里我们新建了两个动画,一个用来控制translationX属性,一个用来控制rotation属性,然后利用一个aniatorSet来播放。可能有人要问,既然有了PropertyValuesHolder为何还要加AnimatorSet,这是因为AnimatorSet更加灵活,PropertyValuesHolder只能控制一个对象的多个属性,但AnimatorSet除了能实现这个功能外还能控制多个对象的属性,同时最重要的是,它还能控制这些动画的播放顺序。主要通过playTogether()、playSequentially()、animSet.play()等方法实现的。
3、如何控制一个没有提供get和set方法的属性
之前提到,我们要控制某个对象的属性,该属性必须有get和set方法,然而,如果某些属性没有get和set方法怎么办呢?不能用属性动画了吗?NO!这里有两种解决方式。
(1)自己加上get和set方法
比如我么有一个LinearLayout,我们想利用动画修改它的宽度,但是LinearLayout并没有直接提供get和set方法设置,所以我门完全可以子弟重写这个LinearLayout,加上一层包装,提供这两个方法,如下
public class MyLinearLayout extends LinearLayout {
public int getMWidth() {
return getLayoutParams().width;
}
public void setMWidth(int mWidth) {
getLayoutParams().width = mWidth;
requestLayout();
}
public MyLinearLayout(Context context) {
super(context);
}
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
这样就有了get和set方法,所以我么就能使用属性动画了
MyLinearLayout llayout = (MyLinearLayout)findViewById(R.id.layout_wrap);
Animator animator = ObjectAnimator.ofInt(llayout,"mWidth",300);
animator.setDuration(3000);
animator.start();
(2)利用ValueAnimator解决
final LinearLayout layout= (LinearLayout) findViewById(R.id.view_value_animator);
ValueAnimator animator = ValueAnimator.ofInt(10,300);
animator.setTarget(layout);
animator.setDuration(3000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();//获得系统帮你计算的值,然后你自己使用这个值来实现动画效果
layout.getLayoutParams().width = value;
layout.requestLayout();
}
});
animator.start();
ValueAnimator用法其实和ObjectAnimator类似,先设定数值的变化范围,然后设定作用目标和变化时间,最后利用start()方法开始,不同的是,ValueAnimator不会帮你改变目标的属性,而是帮助你计算这个值的变化过程,你拿到这个值后可以自己实现目标的某个属性的改变,比如上面的代码中就是用 layout.getLayoutParams().width = value; 来改变LinearLayout的宽度,从而实现一个动画效果。
4、View的animate方法
其实,除了上述的两种方法外,google还为我们封装了一种方式使用属性动画,那就是View的animate方法,我们看一下怎么实现的
view.animate()
.setDuration(2000)
.scaleX(1.5f)
.translationX(300)
.translationY(500)
.start();
从代码可以看出这个方式能够非常便捷的实现一些动画效果。代码很少,就不分析了。
二、自定义动画
这个嘛,本来想试试自己做一些炫酷的动画效果,暂时能力还不行,以后能力够了再更新吧。