Animation
- Animation类是所有动画(scale、alpha、translate、rotate)的基类,以下是关于 Animation 的属性及意义:
- android:duration 动画持续时间,以毫秒为单位
- android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
- android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
- android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
- android:repeatCount 重复次数
- android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
- android:interpolator 设定插值器,其实就是指定的动作效果,比如弹跳效果等
scale
- scale标签是缩放动画,可以实现动态调控件尺寸的效果,有下面几个属性:
- android:fromXScale 起始的X方向上相对自身的缩放比例,浮点值,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍;
- android:toXScale 结尾的X方向上相对自身的缩放比例,浮点值;
- android:fromYScale 起始的Y方向上相对自身的缩放比例,浮点值,
- android:toYScale 结尾的Y方向上相对自身的缩放比例,浮点值;
- android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为起始缩放点;如果是50%,表示在当前控件的左上角加上自己宽度的50%做为起始点;如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为起始点x轴坐标。
- android:pivotY 缩放起点Y轴坐标,取值及意义跟android:pivotX一样。
alpha
- alpha是透明动画,调节控件的透明度,属性如下:
- android:fromAlpha 动画开始的透明度,从0.0 --1.0 ,0.0表示全透明,1.0表示完全不透明
- android:toAlpha 动画结束时的透明度,也是从0.0 --1.0 ,0.0表示全透明,1.0表示完全不透明
rotate
- rotate是旋转动画,控制控件在平面上的旋转角度
- android:fromDegrees 开始旋转的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
- android:toDegrees 结束时旋转到的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
- android:pivotX 旋转中点X坐标
- android:pivotY 旋转中点Y坐标
translate
- translate是平移动画,控制控件水平或垂直移动
- android:fromXDelta 起始点X轴坐标,可以是数值、百分数、百分数p 三种样式
- android:fromYDelta 起始点Y轴从标
- android:toXDelta 结束点X轴坐标
- android:toYDelta 结束点Y轴坐标
set
-
set定义动画的集合,可以将多个动画打包执行,在XML中set的定义方式如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:fillAfter="true"><alpha android:fromAlpha="0.0" android:toAlpha="1.0"/> <scale android:fromXScale="0.0" android:toXScale="1.4" android:fromYScale="0.0" android:toYScale="1.4" android:pivotX="50%" android:pivotY="50%"/> <rotate android:fromDegrees="0" android:toDegrees="720" android:pivotX="50%" android:pivotY="50%"/> </set>
执行动画(XML)
- 在项目的 res -> anim下定义动画(xxx.xml)
- 在代码中加载动画,并让目标控件执行
Animation anim = AnimationUtils.loadAnimation(this, R.anim.xxx);
imag.startAnimation(anim);
Interpolator插值器
- Interpolator赋予动画一些特性,它指定了动画变化的特征,系统提供的Interpolator如下:
- AccelerateDecelerateInterpolator 在动画开始与介绍的地方速率改变比较慢,在中间的时候加速
- AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
- AnticipateInterpolator 开始的时候向后然后向前甩
- AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
- BounceInterpolator 动画结束的时候弹起
- CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
- DecelerateInterpolator 在动画开始的地方快然后慢
- LinearInterpolator 以常量速率改变
- OvershootInterpolator 向前甩一定值后再回到原来位置
- xml动画中添加Interpolator
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
代码生成动画
前面介绍了通过xml定义动画,动画集合,插值器等,其实通过代码也可以做到.
-
ScaleAnimation
ScaleAnimation scaleAnim = new ScaleAnimation(0.0f,1.4f,0.0f,1.4f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
scaleAnim.setDuration(700);//它相当于在xml如下定义 <?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:fromXScale="0.0" android:toXScale="1.4" android:fromYScale="0.0" android:toYScale="1.4" android:pivotX="50" android:pivotY="50" android:duration="700" />
-
AlphaAnimation
AlphaAnimation alphaAnim = new AlphaAnimation(1.0f,0.1f);
alphaAnim.setDuration(3000);
alphaAnim.setFillBefore(true);//对应xml属性如下: //android:fromAlpha="1.0" //android:toAlpha="0.1" //android:duration="3000" //android:fillBefore="true"
-
RotateAnimation
RotateAnimation rotateAnim = new RotateAnimation(0, -650, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnim.setDuration(3000);
rotateAnim.setFillAfter(true);//对应xml属性如下: //android:fromDegrees="0" //android:toDegrees="-650" //android:pivotX="50%" //android:pivotY="50%" //android:duration="3000" //android:fillAfter="true"
-
TranslateAnimation
TranslateAnimation translateAnim = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -80,
Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -80);
translateAnim.setDuration(2000);
translateAnim.setFillBefore(true);//对应xml属性: //android:fromXDelta="0" //android:toXDelta="-80" //android:fromYDelta="0" //android:toYDelta="-80" //android:duration="2000" //android:fillBefore="true"
-
AnimationSet
AlphaAnimation alphaAnim = new AlphaAnimation(1.0f,0.1f);
ScaleAnimation scaleAnim = new ScaleAnimation(0.0f,1.4f,0.0f,1.4f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
RotateAnimation rotateAnim = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);AnimationSet setAnim=new AnimationSet(true); setAnim.addAnimation(alphaAnim); setAnim.addAnimation(scaleAnim); setAnim.addAnimation(rotateAnim); setAnim.setDuration(3000);
Interpolater
ScaleAnimation interpolateScaleAnim=new ScaleAnimation(0.0f,1.4f,0.0f,1.4f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
interpolateScaleAnim.setInterpolator(new BounceInterpolator());
interpolateScaleAnim.setDuration(3000);
Property Animator(属性动画)
ValueAnimator
ValueAnimator只负责对指定的数字区间进行动画运算
我们需要对运算过程进行监听,然后自己对控件做动画操作
-
ValueAnimator的构件方法
public static ValueAnimator ofInt(int... values)
public static ValueAnimator ofFloat(float... values)//他们的参数类型都是可变参数长参数,所以我们可以传入任何数量的值;传进去的值列表,就表示动画时的变化范围; //比如ofInt(2,90,45)就表示从数值2变化到数字90再变化到数字45;所以我们传进去的数字越多,动画变化就越复杂。 //从参数类型也可以看出ofInt与ofFloat的唯一区别就是传入的数字类型不一样, //ofInt需要传入Int类型的参数,而ofFloat则表示需要传入Float类型的参数。
ValueAnimator的常用函数
//设置动画时长,单位是毫秒
ValueAnimator setDuration(long duration)
//获取ValueAnimator在运动时,当前运动点的值
Object getAnimatedValue();
//开始动画
void start()
//设置循环次数,设置为INFINITE表示无限循环
void setRepeatCount(int value)
//设置循环模式 value取值有RESTART,REVERSE,
void setRepeatMode(int value)
//取消动画
void cancel()
//设置插值器
void setInterpolator(TimeInterpolator value)
//延时多久时间开始,单位是毫秒
void setStartDelay(long startDelay)
//完全克隆一个ValueAnimator实例,包括它所有的设置以及所有对监听器代码的处理
ValueAnimator clone()举例说明ValueAnimator的使用方式
ValueAnimator animator = ValueAnimator.ofFloat(0f,400f,50f,300f);
animator.setDuration(3000);
//监听动画变化时的实时值
animator.addUpdateListener(
new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//获取当前的值(这里传入的是float,所以强转为Float)
Float curValueFloat = (Float)animation.getAnimatedValue();
int curValue = curValueFloat.intValue();
//跟随值的变化,而改变控件的属性
tv.layout(curValue,curValue,curValue+tv.getWidth(),
curValue+tv.getHeight());
}
});
animator.start();-
ValueAnimator 监听
/**
* 监听器一:监听动画变化时的实时值
*/
public static interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}
//添加方法为:
//public void addUpdateListener(AnimatorUpdateListener listener)
//移除的方法
//void removeUpdateListener(AnimatorUpdateListener listener);
//void removeAllUpdateListeners();/** * 监听器二:监听动画变化时四个状态 */ public static interface AnimatorListener { void onAnimationStart(Animator animation); void onAnimationEnd(Animator animation); void onAnimationCancel(Animator animation); void onAnimationRepeat(Animator animation); } //添加方法为: //public void addListener(AnimatorListener listener) //void removeListener(AnimatorListener listener); //void removeAllListeners();
-
自定义Interpolator
public class MyInterpolator implements Interpolator {public LinearInterpolator() { } public LinearInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { // input表示动画的时间进度,范围是0到1,随着动画的执行匀速增长 // 返回值表示动画的实际进度,是关于input的一维函数 // 当前的值 = start + (end- start)* 动画进度 return input; } }
-
Evaluator
- 插值器的进度,是如何转换为动画实际的值?
Evaluator就是将动画进度转换为实际值的东西,它定义了转换的规则. - FloatEvaluator 和 IntEvaluator分别对应 ofFloat() 和 ofInt()
当我们定义动画的时候,如果不显示的添加Evaluator,则使用默认的Evaluator
public class IntEvaluator implements TypeEvaluator<Integer> {
public Integer evaluate(float fraction,
Integer startValue, Integer endValue) {
int startInt = startValue;
//当前的值 = start + (end- start)* 动画进度
//可以自定义规则
return (int)(startInt + fraction * (endValue - startInt));
}
}
- 插值器的进度,是如何转换为动画实际的值?
-
ArgbEvaluator (用于处理颜色值过渡转换)
public class ArgbEvaluator implements TypeEvaluator {
public Object evaluate(float fraction,
Object startValue, Object endValue) {
int startInt = (Integer) startValue;
int startA = (startInt >> 24);
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;int endInt = (Integer) endValue; int endA = (endInt >> 24); int endR = (endInt >> 16) & 0xff; int endG = (endInt >> 8) & 0xff; int endB = endInt & 0xff; return (int)((startA + (int)(fraction * (endA - startA))) << 24) | (int)((startR + (int)(fraction * (endR - startR))) << 16) | (int)((startG + (int)(fraction * (endG - startG))) << 8) | (int)((startB + (int)(fraction * (endB - startB)))); } } ... //使用例子 ValueAnimator animator = ValueAnimator.ofInt(0xffffff00,0xff0000ff); animator.setEvaluator(new ArgbEvaluator()); animator.setDuration(3000); animator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int curValue = (int)animation.getAnimatedValue(); tv.setBackgroundColor(curValue); } }); animator.start();
-
ofObject()
public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values);
//ofObject相对于ofInt和ofFloat自由度更大些,相应也更复杂点.个人认为ofObject使用的机会不多,所以简单列举一个例子说明它的用法ValueAnimator animator = ValueAnimator.ofObject(new CharEvaluator(),new Character('A'),new Character('Z')); animator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { char text = (char)animation.getAnimatedValue(); tv.setText(String.valueOf(text)); } }); animator.setDuration(10000); animator.setInterpolator(new AccelerateInterpolator()); animator.start(); //... 自定义Evaluator public class CharEvaluator implements TypeEvaluator<Character> { @Override public Character evaluate(float fraction, Character startValue, Character endValue) { int startInt = (int)startValue; int endInt = (int)endValue; int curInt = (int)(startInt + fraction *(endInt - startInt)); char result = (char)curInt; return result; } }
ObjectAnimator
-
ValueAnimator使用相对比较麻烦,谷歌在ValueAnimator的基础上派生了ObjectAnimator,所以ObjectAnimator可以视为ValueAnimator的封装,使用起来更简单.
public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)... //以下是透明,旋转,位移,缩放动画的定义 ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"alpha",1,0,1); ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0); ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationX",0,270,0); ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationY",0,180,0); ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationX", 0, 200,-200,0); ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationY", 0, 200,-100,0); ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleX", 0, 3, 1); ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleY", 0, 3, 1);
-
why ? 为什么通过一段字符串,就可以执行指定的动画?
- 其实上面这些属性,都有其对应的set函数:
- setAlpha()
- setRotation() / setRotationY() / setRotationX()
- setTranslationY() / setTranslationX()
- setScaleX() / setScaleY()
当我们使用以上方式定义属性动画时,系统会拼接出目标控件对应的set函数,然后通过反射执行.
依次类推,只要控件有某一set函数,我们就可以定义对应的动画,比如:
//setBackgrounColor()
ObjectAnimator animator = ObjectAnimator.ofInt(tv, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
animator.setDuration(8000);
animator.setEvaluator(new ArgbEvaluator());
animator.start();
进一步,自定义控件的时候,我们可以自定义set函数,都可以使用对应的动画
- 其实上面这些属性,都有其对应的set函数:
因为ObjectAnimator派生自ValueAnimator,所以ValueAnimator其它的函数,它都可以使用,这里不再叙述
属性的get函数又有何作用呢 ?
我们已经知道属性的set函数的作用,那么对应的get函数有没有什么特殊的作用呢?
有,OberjectAnimator的构件方法,所需的值都是可变参数,如果只传入一个值呢?动画该怎么执行?
当只有一个值的时候,这个值将是动画的结束值,而开始值,则由相应的get函数返回-
PropertyValuesHolder
PropertyValuesHolder也可以用来构造动画,事实上,前面我们讲的动画的构造,最终都是通过PropertyValuesHolder完成,并且PropertyValuesHolder可以让多个动画效果一起执行,先看下几个系统的函数:
// ObjectAnimator
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)
// PropertyValuesHolder
public static PropertyValuesHolder ofFloat(String propertyName, float... values)
public static PropertyValuesHolder ofInt(String propertyName, int... values)
public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object... values)
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)// 其实已经很明显了,我们可以使用PropertyValuesHolder 构建具体的动画效果, //然后使用 ObjectAnimator 的 ofPropertyValuesHolder函数将一个或多个PropertyValuesHolder 打包创建为动画对象 //以下是 使用PropertyValuesHolder 创建动画的例子: PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("Rotation", 60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f); PropertyValuesHolder colorHolder = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff); ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTextView, rotationHolder, colorHolder); animator.setDuration(3000); animator.setInterpolator(new AccelerateInterpolator()); animator.start(); //关于ofObject的使用方与ObjectAnimator的ofObject大同小异... //ofKeyframe会在下面具体讲解
-
Keyframe(关键帧)
之前我们知道,通过插值器和Evaluator可以控制动画的变化速率,但如果要实现更复杂的效果,就需要定义更复杂的公式.Keyframe同样可以控制动画的速率,使用起来也更简单.在讲自定义插值器的时候,曾提到过,动画的进度在0~1之间,而Keyframe可以让我们指定动画在某一进度点上的值,通过这种方式,我们可以更灵活,更简单的控制动画的速率.
//动画开始的值为 0
Keyframe frame0 = Keyframe.ofFloat(0f, 0);
//动画进度为0.1的时候,值为 -20
Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
//动画结束的时候,值为 0
Keyframe frame2 = Keyframe.ofFloat(1, 0);
//通过 Keyframe 构建 PropertyValuesHolder
PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2);
Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder);
animator.setDuration(1000);
animator.start();//使用Keyframe,每两帧之间默认匀速执行,即线性插值器,更强大的是,我们可以给Keyframe指定插值器, //如果给某个Keyframe设置了插值器,那么从前一帧到这一帧的动画会按插值器执行 public void setInterpolator(TimeInterpolator interpolator) //同样的,Keyframe的构建方式也有以下几种 public static Keyframe ofInt(float fraction, int value) public static Keyframe ofFloat(float fraction, float value) public static Keyframe ofObject(float fraction, Object value) //***需要强调的是,使用Keyframe的时候,最少需要两帧,否则会报错 //***另外第一帧是动画的开始,最后一帧是动画的结束
-
AnimatorSet
顾名思义,AnimatorSet可以联合多个动画一起执行:
//多个动画顺序执行
public void playSequentially(Animator... items);
public void playSequentially(List<Animator> items);
//多个动画同时执行
public void playTogether(Animator... items);
public void playTogether(Collection<Animator> items);//以上方式都比较简单, 我们可以使用AnimatorSet.Builder实现更具体的控制,比如指定动画的执行顺序 // 执行动画 public Builder after(Animator aim) //和前面动画一起执行 public Builder with(Animator anim) //先执行前面的动画,再执行这个动画 public Builder before(Animator anim) //先执行这个动画,再执行前面的动画 public Builder after(Animator anim) //示例如下 ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff); ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0); ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(tv1TranslateY).with(tv2TranslateY).after(tv1BgAnimator); animatorSet.setDuration(2000); animatorSet.start();
AnimatorSet 可以通过*addListener(AnimatorListener listener) *监听其状态的变化
需要注意的是,某些属性可以通过AnimatorSet统一设置,比如: 动画时长,重复次数等.并且如果统一设置了这些属性,那么针对单个动画的设置将无效.
-
使用XML定义属性动画
- 在xml中对应animator总共有三个标签,分别是
<animator /> 对应ValueAnimator
<objectAnimator /> 对应ObjectAnimator
<set /> 对应AnimatorSet
-
animator (以下是animator完整的字段,及对应的值类型)
<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"]
android:interpolator=["@android:interpolator/XXX"]/>- android:duration:每次动画播放的时长
- android:valueFrom:初始动化值;取值范围为float,int和color,如果取值为float对应的值样式应该为89.0,取值为Int时,对应的值样式为:89;当取值为clolor时,对应的值样式为 #333333;
- android:valueTo:动画结束值;取值范围同样是float,int和color这三种类型的值;
- android:startOffset:动画激活延时;对应代码中的startDelay(long delay)函数;
- android:repeatCount:动画重复次数
- android:repeatMode:动画重复模式,取值为repeat和reverse;repeat表示正序重播,reverse表示倒序重播
- android:valueType:表示参数值类型,取值为intType和floatType;与android:valueFrom、android:valueTo相对应。如果这里的取值为intType,那么android:valueFrom、android:valueTo的值也就要对应的是int类型的数值。如果这里的数值是floatType,那么android:valueFrom、android:valueTo的值也要对应的设置为float类型的值。非常注意的是,如果android:valueFrom、android:valueTo的值设置为color类型的值,那么不需要设置这个参数;
- android:interpolator:设置加速器
-
objectAnimator
objectAnimator对比animator多了一条属性
android:propertyName="string"- android:propertyName:对应属性名,即ObjectAnimator所需要操作的属性名
-
set(set标签只有一条属性)
<set android:ordering=["together" | "sequentially"]>- android:ordering:表示动画开始顺序。together表示同时开始动画,sequentially表示逐个开始动画
-
加载XML里定义的动画
ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(context,R.animator.animator);
valueAnimator.start();ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(MyActivity.this, R.animator.object_animator); animator.setTarget(mTv1); animator.start(); AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(MyActivity.this, R.animator.set_animator); set.setTarget(mTv1); set.start();
布局动画
LayoutAnimation
-
XML实现
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="1"
android:animationOrder="normal"
android:animation="@anim/slide_in_left"/>... <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent" android:layoutAnimation="@anim/layout_animation" />
代码实现
//得到一个LayoutAnimationController对象;
LayoutAnimationController controller = new LayoutAnimationController(animation);
//设置控件显示的顺序;
controller.setOrder(LayoutAnimationController.ORDER_REVERSE);
//设置控件显示间隔时间;
controller.setDelay(0.3f);
//为ListView设置LayoutAnimationController属性;
mListView.setLayoutAnimation(controller);
mListView.startLayoutAnimation();各字段解释
delay:指每个Item的动画开始延时,取值是android:animation所指定动画时长的倍数,取值类型可以是float类型,也可以是百分数,默认是0.5;比如我们这里指定的动画是@anim/slide_in_left,而在slide_in_left.xml中指定android:duration=”1000”,即单次动画的时长是1000毫秒,而我们在这里的指定android:delay=”1”,即一个Item的动画会在上一个item动画完成后延时单次动画时长的一倍时间开始,即延时1000毫秒后开始。
animationOrder:指viewGroup中的控件动画开始顺序,取值有normal(正序)、reverse(倒序)、random(随机)
animation:指定每个item入场所要应用的动画。仅能指定res/aim文件夹下的animation定义的动画,不可使用animator动画。
GridLayoutAnimation
-
XML实现
<?xml version="1.0" encoding="utf-8"?>
<gridLayoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:rowDelay="75%"
android:columnDelay="60%"
android:directionPriority="none"
android:direction="bottom_to_top|right_to_left"
android:animation="@android:anim/slide_in_left"/>*** <GridView android:id="@+id/grid" android:layout_width="match_parent" android:layout_height="match_parent" android:columnWidth="60dp" android:gravity="center" android:horizontalSpacing="10dp" android:layoutAnimation="@anim/gride_animation" android:numColumns="auto_fit" android:stretchMode="columnWidth" android:verticalSpacing="10dp"/>
代码实现
GridLayoutAnimationController controller = new GridLayoutAnimationController(animation);
controller.setColumnDelay(0.75f);
controller.setRowDelay(0.5f);
controller.setDirection(GridLayoutAnimationController.DIRECTION_BOTTOM_TO_TOP|GridLayoutAnimationController.DIRECTION_LEFT_TO_RIGHT);
controller.setDirectionPriority(GridLayoutAnimationController.PRIORITY_NONE);
grid.setLayoutAnimation(controller);
grid.startLayoutAnimation();各属性解释
rowDelay:每一行动画开始的延迟。与LayoutAnimation一样,可以取百分数,也可以取浮点数。取值意义为,当前android:animation所指动画时长的倍数。 columnDelay:每一列动画开始的延迟。取值类型及意义与rowDelay相同。 directionPriority:方向优先级。取值为row,collumn,none,意义分别为:行优先,列优先,和无优先级(同时进行);
direction:gridview动画方向。 取值有四个:
*left_to_right:列,从左向右开始动画
right_to_left :列,从右向左开始动画
top_to_bottom:行,从上向下开始动画
bottom_to_top:行,从下向上开始动画 *
这四个值之间可以通过“|”连接,从而可以取多个值。
很显然left_to_right和right_to_left是互斥的,
top_to_bottom和bottom_to_top是互斥的。
如果不指定 direction字段,
默认值为left_to_right | top_to_bottom;
即从上往下,从左往右。
animation: gridview内部元素所使用的动画。
布局增加/移除动画
- android:animateLayoutChanges="true"
只要给布局添加该属性,它内部的控件在添加和删除时,是会带有默认动画 - LayoutTransaction ,允许我们自定义动画效果
LayoutTransaction transitioner = new LayoutTransition();
ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotation", 0f, 90f, 0f);
//设置动画
//第一个参数int transitionType:表示当前应用动画的对象范围,取值有:
//APPEARING —— 添加元素的动画
//DISAPPEARING —— 移除元素的动画
//CHANGE_APPEARING —— 添加元素时,其它元素的动画(该动画必须通过PropertyValuesHolder创建)
//CHANGE_DISAPPEARING —— 移除元素时,其它元素的动画(该动画必须通过PropertyValuesHolder创建)
//第二个参数Animator animator:表示当前所选范围的控件所使用的动画。
transitioner.setAnimator(LayoutTransition.DISAPPEARING, animOut);
//将LayoutTransaction设置进ViewGroup
linearLayout.setLayoutTransition(mTransitioner);
因为LayoutTransaction 使用的机会不多,且实际应用相对麻烦,所以不再详细说明