前言
此篇主要介绍Android animation xml动画资源Property Animation。。
android动画资源可以分2中类型:一种是以Property为单位动画效果,这种类型的动画主要是对某一个或者多个属性设置动画效果,比如textColor,layout_x等;另一种是以View为单位的动画效果,比如Tween Animation(补间动画)和Frame Animation(逐帧动画)。
一、Property Animation
给控件的某一个属性设置动画效果,比如颜色变化、透明度变化等。
使用也很简单,先来看看标准的语法格式,如下:
1、语法格式
<set
android:ordering=["together" | "sequentially"]>
<objectAnimator
android:propertyName="string"
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>
<animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>
<set>
...
</set>
</set>
解析说明:
上面的语法属性基本是字面意思。在此只说明3个属性:
android:ordering 的取值together和sequentially,分别表示同时执行和按照顺序执行。
android:startOffset 表示延迟多久开始。单位是毫秒。
android:valueType取值intType和floatType。表示当前valueFrom和valueTo的取值类型。如果value取值为颜色值,则不需要指定valueType的类型。
<ObjectAnimator>和<animator>的区别在下面的使用中会提到。
2、使用
说到动画XML资源的使用,必须先介绍几个属性动画相关的Java类:ObjectAnimator、ValueAnimator、AnimatorSet。其中ObjectAnimator是ValueAnimator的子类,AnimatorSet是控制多个动画播放的控制类。接下来的实例中,会使用到这3个类。上面语法格式中提到的<ObjectAnimator>和<animator>,分别对应的Java类为ObjectAnimator和ValueAnimator。
由此可知<animator>只是<ObjectAnimator>一个比较抽象的表示形式,没有制定具体的Property Name,因为ObjectAnimator是ValueAnimator的子类,ValueAnimator或者说<animator>是具有更抽象和灵活的特性。
接下来,我们使用同一个动画效果,介绍<ObjectAnimator>和<animator>的使用和区别。
例子:
1、使用<ObjectAnimator>和ObjectAnimator来实现动画效果。
XML动画资源文件res/animator/property_animation.xml
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="x"
android:duration="5000"
android:startOffset="1000"
android:valueFrom="1"
android:valueTo="700"
android:repeatCount="3"
android:repeatMode="reverse"/>
改变属性x值从1到700,重复3次,重复方式为reverse,延迟1秒开始,持续5秒钟。
布局文件res/layout/main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ab_ll">
<TextView
android:id="@+id/text01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:background="@android:color/black" />
</RelativeLayout>
布局中只有一个TextView控件。 我们要实现的就是将TextView从左边滑动到右边的动画效果。下面看看在activity中的代码实现:
textView1 = (TextView) findViewById(R.id.text01);
//将XML动画资源实例化为ObjectAnimator对象
ObjectAnimator animation = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.property_animation);
animation.setTarget(textView1);
animation.start();
这就是<ObjectAnimator>的使用方式,很简单。使用的代码只有3行。动画效果提前在xml中配置好。效果如下:
2、使用<animator>和ValueAnimator实现同上的动画效果。
之所以使用同一个例子,主要是介绍<animator>和<objectAnimator>的区别和相同点,以及<animator>的使用。
XML动画资源文件res/animator/property_animation.xml
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="5000"
android:startOffset="1000"
android:valueFrom="1"
android:valueTo="700"
android:repeatCount="3"
android:repeatMode="reverse"/>
相比上面的<objectAnimator>,<animator>只是没有propertyName属性,也就是说<animator>没有制定特定的属性类型。
布局文件同上,就不重复粘贴了。关键是activity中的使用代码会跟ObjectAnimator有所不同:
//将XML动画资源实例化为ObjectAnimator对象
ValueAnimator animation = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.property_animation);
animation.setTarget(textView1);
animation.start();
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
textView1.setX((Float)animation.getAnimatedValue());
}
});
通过上面的代码可以发现,和ObjectAnimator相比,多了animation.addUpdateListener这个方法,此方法是动画生命周期数据变化的一个监听,在这个方法中,我们对需要Target View进行属性值的设置,从而达到想要的动画效果。
相比<ObjectAnimator>, <animator>的重用性更好,更加灵活。比如我们需要对X和Y轴同时进行动画,我们只需要在上面的代码中加上一行代码就行,如下:
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
textView1.setX((Float)animation.getAnimatedValue());
textView1.setY((Float)animation.getAnimatedValue());
}
});
这样X轴、Y轴同时都进行移动,效果如下:
那这样看来感觉<objectAnimator>只能实现单个属性的动画,<animator>可以多个属性具有同一个动画生命周期。这也是<animator>复用性更好,更灵活的原因。
如果要使用<objectAnimator>实现同时完成多个属性的动画效果,也是有办法的,具体操作如下:
xml动画资源文件:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<objectAnimator
android:propertyName="x"
android:duration="5000"
android:startOffset="1000"
android:valueFrom="1"
android:valueTo="700"
android:repeatCount="3"
android:repeatMode="reverse"/>
<objectAnimator
android:propertyName="y"
android:duration="5000"
android:valueFrom="1"
android:valueTo="700"
android:repeatCount="3"
android:repeatMode="reverse"/>
</set>
没错,就是使用2个<objectAnimator>完成。如上同时写上X和Y的动画属性。然后,在Java代码中使用如下:
//将XML动画资源实例化为ObjectAnimator对象
AnimatorSet animation = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.property_animation);
animation.setTarget(textView1);
animation.start();
注意,上面使用的AnimatorSet类,这是一个可以同时播放多个动画效果的类。 这样就可以同时改变X、Y轴的值,实现动画效果。
动画的监听事件:
animation.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
//动画开始
}
@Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
//动画重复
}
@Override
public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
//动画生命周期结束
}
@Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
//动画取消
}
});
通过动画开始和结束的监听事件,我们可以完成一些效果,比如动画结束后调转、或者隐藏等。
3、扩展使用
上面我们介绍了Animation的基本语法和简单使用。接下来,我们稍微进阶一下用法。
比如:
当TextView移动的过程中,当X移动到0、40、80距离是,字体颜色分别发生3种不同的变化。如下图效果:
实现代码:(此处完全使用Java代码完成)
ValueAnimator animation = new ValueAnimator();
animation.setDuration(5000);
animation.setObjectValues(new MineAnimatorType());
animation.setRepeatMode(Animation.REVERSE);
animation.setRepeatCount(4);
animation.setInterpolator(new LinearInterpolator());
animation.setEvaluator(new TypeEvaluator<MineAnimatorType>() {
@Override
public MineAnimatorType evaluate(float fraction,
MineAnimatorType startValue, MineAnimatorType endValue) {
// TODO Auto-generated method stub
MineAnimatorType mineAnimatorType = new MineAnimatorType();
Log.d("ddd", "-->"+fraction*200);
mineAnimatorType.x = fraction*200;
mineAnimatorType.y = fraction*1.5F*200;
if (mineAnimatorType.x > 80) {
mineAnimatorType.color = Color.RED;
} else if (mineAnimatorType.x < 40) {
mineAnimatorType.color = Color.BLUE;
} else {
mineAnimatorType.color = Color.GREEN;
}
return mineAnimatorType;
}
});
animation.start();
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
MineAnimatorType mineAnimatorType=(MineAnimatorType) animation.getAnimatedValue();
textView1.setX(mineAnimatorType.x);
textView1.setY(mineAnimatorType.y);
textView1.setTextColor(mineAnimatorType.color);
}
});
1、以上setInterpolator()方法是改变动画播放速度,取值如下:
AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
AnticipateInterpolator 开始的时候向后然后向前甩
AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
BounceInterpolator 动画结束的时候弹起
CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator 在动画开始的地方快然后慢
LinearInterpolator 以常量速率改变
OvershootInterpolator 向前甩一定值后再回到原来位置
AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
AnticipateInterpolator 开始的时候向后然后向前甩
AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
BounceInterpolator 动画结束的时候弹起
CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator 在动画开始的地方快然后慢
LinearInterpolator 以常量速率改变
OvershootInterpolator 向前甩一定值后再回到原来位置
class MineAnimatorType{
public float x;
public float y;
public int color;
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
}
以上是动画扩展使用的基本方式。其中setObjectValues定义指定的数据类型,setInterpolator设定动画速率,setEvaluator此方法为自定义值的变化方式。
实例2:画圆的动画,对上面的例子进行修改之后,可以实现画圆动画。
画园和画直线唯一的区别就是X、Y的值变化的方式不一样,所以我们只需要改变setEvaluator方法中X\Y的计算方式就行了,代码如下:
animation.setEvaluator(new TypeEvaluator<MineAnimatorType>() {
@Override
public MineAnimatorType evaluate(float fraction,
MineAnimatorType startValue, MineAnimatorType endValue) {
// TODO Auto-generated method stub
MineAnimatorType mineAnimatorType = new MineAnimatorType();
Log.d("ddd", "-->"+fraction);
mineAnimatorType.x = (float) Math.cos(fraction*Math.PI*2)*100+300;
mineAnimatorType.y = (float) (Math.sin(fraction*Math.PI*2)*100)+300;
return mineAnimatorType;
}
});
效果如下:
以上主要是介绍XML动画资源之Property Animation的使用,和一些简单的示例。
通过这些基本的用法,加上合理的算法,我们可以完成很炫的效果。