Android 属性动画 详解

Android动画类型:
View Animation(即所谓的Tween Animation补间动画):View Animation相当简单,不过只能支持简单的缩放、平移、旋转、透明度基本的动画
Drawable Animation (即所谓Frame Animation逐帧动画)
Property Animation 利用对象的属性变化形成动画的效果
Tween Animation和Frame Animation的动态效果只适应一个控件,或者说多个控件同时执行一种效果。
Property Animation可同时对一个对象应用多个动画,动画期间可以进行交互设置。

Property Animation 和 View Animation的区别
1、View Animation只能用于View及View的子类的对象;Property Animation则没有这样的限制
2、View Animation限制较多,一些动画,只能用于没有background的view,否则会打不到预期效果;如缩放一个view时,这是缩小了view的外观,她的background并没有改变,所以如果background不是透明的,则会露馅。
3、View Animation只是简单的改变View的绘制,并不会改变View本身。比如,你将一个button从位置1移动到位置2,但是触发点击事件的位置还是在位置1。Property Animation这不会出现这种情况。
View Animation使用的代码较少,启动所花费的时间也短

PropertyAnimation
属性动画,就是利用对象的属性变化形成动画的效果。
属性动画的类可以用Animator这个抽象类来表示,通常使用它的子类:AnimatorSet和ValueAnimator,
同时ValueAnimator有两个子类分别是ObjectAniamtor和TimeAnimator。

1、定义属性动画的XML资源的时候通常可以是如下三个元素之一作为根元素:
<set>元素:
—该资源元素代表的是AniamtorSet类:动画集合,即同时对一个对象应用多个动画,这些动画可以同时播放也可以对不同动画设置不同的延迟
这个类可以包含<set>,<objectAniamtor>, <animator>三个子元素。
<objectAnimator>元素:
—用于定义objectAniamtor类,一个对象的一个属性动画。
<animator>元素:
—用于定义ValueAnimator类,在一个特定的时间里执行一个动画。
<set> <objectAniamtor> <animator>定义此三种元素的xml文件必须位于res/animator目录下

<set android:ordering="[together|sequentially]"> // 控制子动画启动顺序:默认(together)同时启动,sequentially按先后顺序启动<objectAnimatorandroid:propertyName="string" //要执行动画的属性名,如"alpha" "backgroundColor" android:duration="int"   //int型,动画的持续时间,单位毫秒,默认为300毫秒android:valueFrom="float|int|color" //float int color类型,动画的起始点,若没有指定,系统会通过属性的get方法获取,颜色为6位十六进制的数字表示android:valueTo="float|int|color"
//float int color类型,必须设置的节点属性,表明动画的结束点,如果是颜色的话,由6位十六进制的数字表示android:startOffset="int"
//int型,动画延迟时间,从调用start方法后开始计算,单位毫秒android:repeatCount="int"
//int型,动画重复次数,默认为0,不重复执行,"-1"无线循环,"1"动画执行完后再重复执行一次android:interpolator=""
//定义动画变化速率的接口,所有插值器都必须实现此接口,如线性、非线性插值器android:repeatMode="[reapeat|reverse]" // int型,重复模式,该值必须为正数或-1,"reverse"动画向相反的方向执行、"repeat"动画每次都从头开始循环android:valueType="[intType|floatType]"/> // intType和floatType两种:分别说明动画值为int和float型,若value是一个颜色,就不需指定,动画框架会自动处理颜色值<animator      android:duration="int"android:valueFrom="float|int|color"android:valueTo="float|int|color"android:startOffset="int"android:repeatCount="int"android:interpolator=""android:repeatMode="[reapeat|reverse]"android:valueType="[intType|floatType]"/><set>....</set>
</set>

//示例
//res/animator/animSet.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"  android:ordering="sequentially" >  <objectAnimator  android:duration="2000"  android:propertyName="translationX"  android:valueFrom="-500"  android:valueTo="0"  android:valueType="floatType" >  </objectAnimator>   <set android:ordering="together" >  <objectAnimator  android:duration="3000"  android:propertyName="rotation"  android:valueFrom="0"  android:valueTo="360"  android:valueType="floatType" >  </objectAnimator>  <set android:ordering="sequentially" >  <objectAnimator  android:duration="1500"  android:propertyName="alpha"  android:valueFrom="1"  android:valueTo="0"  android:valueType="floatType" >  </objectAnimator>  <objectAnimator  android:duration="1500"  android:propertyName="alpha"  android:valueFrom="0"  android:valueTo="1"  android:valueType="floatType" >  </objectAnimator>  </set>  </set>
</set> 

//代码访问

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.animSet);
animator.setTarget(view);
animator.start();  

ValueAnimator
属性动画中的时间驱动,管理着动画时间的开始、结束属性值,相应时间属性值计算方法等。
包含所有计算动画值的核心函数以及每一个动画时间节点上的信息、一个动画是否重复、是否监听更新事件等,并且还可以设置自定义的计算类型。
ValueAnimator有工厂方法ofInt()、ofFloat()、ofObject()用于不同的类型

ValueAnimator animator = ValueAnimator.ofFloat(0, mContentHeight);
animator.setTarget(view);   //设置作用目标
animator.setDuration(5000).start();
//ValueAnimator.AnimatorUpdateListener
animator.addUpdateListener(new AnimatorUpdateListener() { // ValueAnimator没有设置属性,需要通过updateListener里设置属性才会生效。@Overridepublic void onAnimationUpdate(ValueAnimator animation){ //通过当前动画的计算去修改任何属性 ,帧刷新时调用,用于使用ValueAnimator计算出的属性值float value = (float) animation.getAnimatedValue();view.setXXX(value);  //必须通过这里设置属性值才有效,ValueAnimator不直接操作属性值,所以要操作对象的属性可以不需要setXXX与getXXX方法view.mXXX = value;  //不需要setXXX属性方法}
});

ObjectAnimator
1、继承自ValueAnimator,允许你指定要进行动画的对象以及该对象的一个属性。该类会根据计算得到的新值自动更新属性(不同于ValueAnimator,ValueAnimator需另写动画更新逻辑),
2、ObjectAnimator使用有一定的限制,它需要目标对象的属性提供指定的处理方法(譬如提供getXXX,setXXX方法)。
3、ObjectAnimator类提供了ofInt、ofFloat、ofObject这个三个常用的方法,这些方法都是设置动画作用的元素、属性、开始、结束等任意属性值,
当属性值(上面方法的参数)只设置一个时就把通过getXXX反射获取的值作为起点,设置的值作为终点;如果设置两个(参数),那么一个是开始、另一个是结束。
ObjectAnimator的动画原理是不停的调用setXXX方法更新属性值,所有使用ObjectAnimator更新属性时的前提是Object必须声明有getXXX和setXXX方法。
通常使用ObjectAnimator设置View已知的属性来生成动画,而一般View已知属性变化时都会主动触发重绘图操作,所以动画会自动实现
使用示例:
a: xml + 代码
//res/animator/objectColor => ObjectAnimator xml设置

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:duration="5000"android:propertyName="backgroundColor"android:repeatCount="infinite"android:repeatMode="reverse"android:valueFrom="#ff8080"android:valueTo="#8080ff"android:valueType="intType" >
</objectAnimator>

//ObjectAnimator操作代码

ObjectAnimator oa = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.objectColor); /加载属性动画需要用到AnimatorInflater类
oa.setEvaluator(new ArgbEvaluator()); //用于动画计算的需要,如果开始和结束的值不是基本类型的时候,这个方法是需要的。
oa.setTarget(imageView); //设置动画的设置目标
oa.start();

//res/animator/objectScale => ObjectAnimator xml设置

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:propertyName="scaleX"  android:valueFrom="1.0" android:valueTo="2.0" android:valueType="floatType">
</objectAnimator> //ObjectAnimator操作代码
Animator anim = AnimatorInflater.loadAnimator(this,R.animator.objectScale);
anim.setTarget(view);
anim.start(); 

b:纯代码定义、使用

ObjectAnimator.ofFloat(view, "rotationY", 0.0f, 360.0f).setDuration(1000).start();
float curTranslationX = textview.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "translationX", curTranslationX, -500f, curTranslationX);
//ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "scaleY", 1f, 3f, 1f);
animator.setDuration(5000);
animator.start();
ObjectAnimator mObjectAnimator= ObjectAnimator.ofInt(view, "customerDefineAnyThingName", 0,  1) .setDuration(2000);//若Object不是View,或者设置的属性没有触发重绘,或者在重绘时需要做自己的操作,则可以通过addUpdateListener()方法添加AnimatorUpdateListener监听:
mObjectAnimator.addUpdateListener(new AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {//int value = animation.getAnimatedValue();  可以获取当前属性值//view.postInvalidate();  可以主动刷新//view.setXXX(value);//view.setXXX(value);//......可以批量修改属性}
});ObjectAnimator anim = ObjectAnimator.ofFloat(view, "op", 1.0F,  0.0F).setDuration(500); // "op", 设置的属性不会触发重绘
anim.start();
anim.addUpdateListener(new AnimatorUpdateListener()  {   @Override  public void onAnimationUpdate(ValueAnimator animation)  {  //动画更新监听事件中,对view进行操作,触发view的重绘float cVal = (Float) animation.getAnimatedValue();  view.setAlpha(cVal);  view.setScaleX(cVal);  view.setScaleY(cVal);  }
});

PropertyValuesHolder
多属性动画同时工作管理类。有时候我们需要同时修改多个属性,那就可以用到此类–针对同一个对象的多个属性,要同时作用多种动画。
ValueAnimator和ObjectAnimator的ofPropertyValuesHolder(view,…)可实现多属性动画

//平移的过程中同时改变X、Y轴的缩放,
PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2, pvh3).setDuration(1000).start(); //可以实现同时修改多个属性的动画
//移动过程中渐进显示
PropertyValuesHolder a1 = PropertyValuesHolder.ofFloat("alpha", 0f, 1f);
PropertyValuesHolder a2 = PropertyValuesHolder.ofFloat("translationY", 0, viewWidth);
......
ObjectAnimator.ofPropertyValuesHolder(view, a1, a2, ......).setDuration(1000).start(); // 可以实现同时修改多个属性的动画

AnimatorSet
对于一个对象同时作用多个属性动画效果,同时也能实现更为精确的顺序控制。

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 300f);
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 0f, 1f);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(imageView, "scaleY", 1f, 0f, 1f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(1000);
animatorSet.playTogether(objectAnimator, objectAnimator1, objectAnimator2);
//animatorSet.play(objectAnimator).with(objectAnimator1);
//animatorSet.play(objectAnimator1).with(objectAnimator2);
animatorSet.start();  ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);
ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
AnimatorSet animSet = new AnimatorSet();
animSet.play(rotate).with(fadeInOut).after(moveIn);
animSet.setDuration(5000);
animSet.start();

在属性动画中,AnimatorSet正是通过playTogether()、playSquentially()、play().width()、play().defore()、play().after()支持链式编程这些方法来控制多个动画的协同工作方式,从而做到对动画播放顺序的精确控制。

AnimatorListener / AnimatorListenerAdapter
一个完整的动画具有Start、Repeat、End、Cancel四个过程,动画事件的监听:通过Android接口AnimatorListener,AnimatorListenerAdapter:

ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "alpha", 0.5F);
anim.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) { }
});
或使用AnimatorListenerAdapter,AnimatorListenerAdapter使用空方法实现了AnimatorListener的所有方法
anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation); }
});
anim.start();  

Evaluators
Evaluators就是属性动画系统如何去计算一个属性值。它们通过Animator提供的
动画的起始和结束值去计算一个动画的属性值。
IntEvaluator: 整数属性值。
FloatEvaluator:浮点数属性值。
ArgbEvaluator: 十六进制color属性值。
TypeEvaluator: 用于定义属性值计算方式的接口,有int、float、color类型,根据属性的起始、结束值和插值一起计算出当前时间的属性值
//TypeEvaluator接口代码

public interface TypeEvaluator<T> {//根据动画进度,属性起始值和结束值,计算出当前值public T evaluate(float fraction, T startValue, T endValue);
}

Interpolators
插值器可以定义动画变换速率,主要是控制目标变量的值进行对应的变化。
AccelerateDecelerateInterpolator —先加速后减速,在动画开始与结束的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator —加速,在动画开始的地方速率改变比较慢,然后开始加速
DecelerateInterpolator —减速,在动画开始的地方快然后慢
AnticipateInterpolator —先向相反方向改变一段再加速播放
AnticipateOvershootInterpolator —先向相反方向改变,再加速播放,会超出目标值然后缓慢移动至目标值,类似于弹簧回弹
BounceInterpolator —动画结束的时候弹起,快到目标值时值会跳跃
CycleInterpolator —动画循环播放特定的次数,速率改变沿着正弦曲线,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)
LinearInterpolator —以常量速率改变,线性均匀改变
OvershootInterpolator —最后超出目标值然后缓慢改变到目标值,类似弹簧效果
PathInterpolator —路径插值器
TimeInterpolator:一个允许自定义Interpolator的接口,以上都实现了该接口

使用示例:

ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration(5000);
valueAnimator.setObjectValues(new float[2]); //设置属性值类型
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setEvaluator(new TypeEvaluator<float[]>() {@Overridepublic float[] evaluate(float fraction, float[] startValue,float[] endValue){//实现自定义规则计算的float[]类型的属性值float[] temp = new float[2];temp[0] = fraction * 2;temp[1] = (float)Math.random() * 10 * fraction;return temp;}
});
valueAnimator.start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float[] xyPos = (float[]) animation.getAnimatedValue();view.setHeight(xyPos[0]);   //通过属性值设置View属性动画view.setWidth(xyPos[1]);    //通过属性值设置View属性动画}
});

Keyframes关键帧
一个Keyframe对象有一个time/value对组成,用于指定在特定时间点,动画的状态。每一个关键帧都可以有它自己的插值器,用来控制前一个关键帧和此关键帧的关系。
1、使用方法ofInt(), ofFloat(), 和ofObject()中的一个来获得一个关键帧实例。
2、然后调用PropertyValuesHolder的工厂方法ofKeyframe()来获得一个PropertyValuesHolder对象。
3、将PropertyValuesHolder对象作为ObjectAnimator.ofPropertyValuesHolder()方法的参数,即可构造出一个对象。
示例

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation);
rotationAnim.setDuration(5000ms);

ViewPropertyAnimator
动画是属性动画的拓展,在Android API 12中,View添加了animate方法,具体如下:

public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource {...public ViewPropertyAnimator animate() {if (mAnimator == null) {mAnimator = new ViewPropertyAnimator(this); //当前视图的视图属性动画}return mAnimator;}...
}

通过View的animate()方法可以得到一个ViewPropertyAnimator的属性动画,ViewPropertyAnimator提供了一种非常方便的方法为View的部分属性设置动画,它可以直接使用一个Animator对象设置多个属性的动画;
在多属性设置动画时,它比上面的ObjectAnimator更加酷炫、高效,因管理多个属性的invalidate方法统一调度、运行、触发,而不像上面分别调用,所以还会有一些性能优化。

myView.animate().x(0f).y(100f).start();myView.animate() // need API12 .alpha(0).y(mScreenHeight / 2).setDuration(1000)    .withStartAction(new Runnable() {  // need API 12 @Overridepublic void run() { Log.e(TAG, "START"); } }).withEndAction(new Runnable() {  // need API 16 @Overridepublic void run()  { Log.e(TAG, "END"); runOnUiThread(new Runnable() { @Overridepublic void run() { myView.setY(0); myView.setAlpha(1.0f); } }); } }).start(); 

LayoutAnimation LayoutTransition布局动画
LayoutAnimation
LayoutAnimation它是用来控制ViewGroup中所有的child view显示的动画,使用方式: xml定义使用, 代码定义方式
1、
a:LayoutAnimation动画直接在xml中定义(res/anim/customer_anim.xml):
//res/anim/slide_right.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"   android:interpolator="@android:anim/accelerate_interpolator">  <translate android:fromXDelta="-100%p" android:toXDelta="0"  android:duration="@android:integer/config_shortAnimTime" />
</set>

//res/animator/layout_anim.xml

<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"  android:delay="30%"   //动画播放的延时,可以是百分比,也可以是float小数,其中delay的单位为秒android:animationOrder="reverse"  //动画的播放顺序,有三个取值normal(0,顺序)、reverse(1,反序)、random(2,随机)android:animation="@anim/slide_right"/> //指向子控件所要播放的动画(表示孩子显示时的具体动画)

b:在ViewGroup的layout xml文件中设置:

<ListView...
    android:layoutAnimation="@animator/layout_anim"/>

2、代码中使用:
//ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1);
//sa.setDuration(2000);
//LayoutAnimationController controller = new LayoutAnimationController(sa, 0.5f); //设置布局动画的显示
//LayoutAnimationController 的第一个参数,是需要作用的动画,而第二个参数,则是每个子View显示的delay时间

Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_right);   //得到一个LayoutAnimationController对象; 

//LayoutAnimationController可实现一个界面中的多个控件按照相同的动画方式但是每个控件完成该动画的时刻不同

LayoutAnimationController controller = new LayoutAnimationController(animation);   //设置控件显示的顺序;
controller.setOrder(LayoutAnimationController.ORDER_REVERSE);   //设置控件显示间隔时间;
controller.setDelay(0.3);   //为ListView设置LayoutAnimationController属性;
listView.setLayoutAnimation(controller);
listView.startLayoutAnimation();  public static final int ORDER_NORMAL = 0; //顺序
public static final int ORDER_REVERSE = 1; //反序
public static final int ORDER_RANDOM = 2; //随机 

LayoutTransition
LayoutTransition是从API Level 11出现的。LayoutTransition的动画效果只有当ViewGroup中有View添加、删除、隐藏、显示的时候才会体现出来。
它也有两种使用方式: xml定义使用, 代码定义方式
1、xml中使用系统默认的LayoutTransition动画:

<LinearLayout android:id="@+id/container"android:animateLayoutChanges="true"...
/> 

在ViewGroup添加如上xml属性默认是没有任何动画效果的,当设置如上属性,然后调用ViewGroup的addView、removeView方法时就能看见系统默认的动画效果(即ViewGroup内部东东发生改变时才有效)。

mContainer.addView(newView, 0);

2、代码中使用LayoutTransition动画:
LayoutTransition类中主要的五种容器转换动画类型,具体如下:
LayoutTransition.APPEARING — 当一个View在ViewGroup中出现时,对此View设置的动画
LayoutTransition.CHANGE_APPEARING — 当一个View在ViewGroup中出现时,对此View对其他View位置造成影响,对其他View设置的动画
LayoutTransition.DISAPPEARING — 当一个View在ViewGroup中消失时,对此View设置的动画
LayoutTransition.CHANGE_DISAPPEARING — 当一个View在ViewGroup中消失时,对此View对其他View位置造成影响,对其他View设置的动画
LayoutTransition.CHANGE — 不是由于View出现或消失造成对其他View位置造成影响,然后对其他View设置的动画
注意:
动画到底设置在谁身上,此View还是其他View

代码中使用系统默认的LayoutTransition动画

LayoutTransition mTransitioner = new LayoutTransition();
mViewGroup.setLayoutTransition(mTransitioner);  

动画使用示例:

private void setupCustomAnimations() {  LayoutTransition mTransitioner = new LayoutTransition(); // 动画:CHANGE_APPEARING  // Changing while Adding  PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1);  PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1);  PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 1);  PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1);  PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX", 1f, 0f, 1f);  PropertyValuesHolder pvhScaleY = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f, 1f);  final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(  this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScaleX,  pvhScaleY).setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_APPEARING));  //通过使用LayoutTransition的方法setAnimator(),传入一个Animator和一个LayoutTransition类中定义的五种容器转换动画类型之一,来定制用于ViewGroup的动画       mTransitioner.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);  changeIn.addListener(new AnimatorListenerAdapter() {  public void onAnimationEnd(Animator anim) {  View view = (View) ((ObjectAnimator) anim).getTarget();  view.setScaleX(1f);  view.setScaleY(1f);  }  });  // 动画:CHANGE_DISAPPEARING  // Changing while Removing  Keyframe kf0 = Keyframe.ofFloat(0f, 0f);  Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);  Keyframe kf2 = Keyframe.ofFloat(1f, 0f);  PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);  final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhRight,  pvhBottom, pvhRotation).setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_DISAPPEARING));  mTransitioner.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut);  changeOut.addListener(new AnimatorListenerAdapter() {  public void onAnimationEnd(Animator anim) {  View view = (View) ((ObjectAnimator) anim).getTarget();  view.setRotation(0f);  }  });  // 动画:APPEARING  // Adding  ObjectAnimator animIn = ObjectAnimator.ofFloat(null, "rotationY", 90f, 0f).setDuration(mTransitioner.getDuration(LayoutTransition.APPEARING));  mTransitioner.setAnimator(LayoutTransition.APPEARING, animIn);  animIn.addListener(new AnimatorListenerAdapter() {  public void onAnimationEnd(Animator anim) {  View view = (View) ((ObjectAnimator) anim).getTarget();  view.setRotationY(0f);  }  });  // 动画:DISAPPEARING  // Removing  ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotationX", 0f, 90f).setDuration(mTransitioner.getDuration(LayoutTransition.DISAPPEARING));  mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, animOut);  animOut.addListener(new AnimatorListenerAdapter() {  public void onAnimationEnd(Animator anim) {  View view = (View) ((ObjectAnimator) anim).getTarget();  view.setRotationX(0f);  }  });  mViewGroup.setLayoutTransition(mTransitioner);  }

Android 属性动画 详解相关推荐

  1. Android 属性动画详解

    Component 是一个强大的.完善的组件化框架. 欢迎大家使用 请尊重别人劳动成果         转载请注明出处:http://blog.csdn.net/u011692041/article/ ...

  2. android+动画队列,Android属性动画详解

    前言 属性动画是Android 3.0(API 11)新加入的动画框架,属性动画弥补了视图动画的很多短板,因此已经成为大多数动画场景的首选框架. 目录 目录 1. 属性动画出现的原因 在属性动画出现以 ...

  3. Android Animation动画详解(二): 组合动画特效

    前言 上一篇博客Android Animation动画详解(一): 补间动画 我已经为大家介绍了Android补间动画的四种形式,相信读过该博客的兄弟们一起都了解了.如果你还不了解,那点链接过去研读一 ...

  4. android动画详解二 属性动画原理

    property动画是一个强大的框架,它几乎能使你动画任何东西.你可以定义一个动画来改变对象的任何属性,不论其是否被绘制于屏幕之上.一个属性动画在一定时间内多次改变一个属性(对象的一个字段)的值.要动 ...

  5. android动画详解

    转自:工匠若水 http://blog.csdn.net/yanbober 1 背景 不能只分析源码呀,分析的同时也要整理归纳基础知识,刚好有人微博私信让全面说说Android的动画,所以今天来一发A ...

  6. Android 动画详解-思维导图版

    转载请注明链接: https://blog.csdn.net/feather_wch/article/details/81503233 涉及视图动画(补间动画.逐帧动画).属性动画三种动画的使用方法, ...

  7. css动画定义,css3的动画(animation)属性的详解(附代码)

    本篇文章给大家带来的内容是关于css3的动画(animation)属性的详解(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. css3动画(animation)具有以下属性: ...

  8. android preference属性,Android进阶——Preference详解之Preference系的基本应用和管理(二)...

    并非我们第一次打开相应界面之后就会自动创建对应的SharedPreferences文件,而是在我们改变了原有状态时候喎�"/kf/ware/vc/" target="_b ...

  9. CSS3动画属性 animation详解(看完就会)

    CSS3动画属性 animation 文章包含个人理解错误请指出   往期文章 [css高级]变量详解 轮播图swiper框架的基本使用 [Transform3D]转换详解(看完就会) [css动画] ...

最新文章

  1. ad 原理图差分线_采用差分PulSAR ADC AD7982转换单端信号电路图
  2. python常用指令速查
  3. 大剑无锋之mysql列转行【面试推荐】
  4. Android系统JNI的实现方式
  5. jQuery datepicker和jQuery validator 共用时bug
  6. 互联网大佬学历背景大揭秘,看看是你的老乡还是校友
  7. 【工具使用系列】关于 MATLAB 神经网络故障诊断,你需要知道的事
  8. ORA-28002 Oracle口令过期
  9. 示波器采样速率单位Ms/s、Gs/s
  10. Pandas DataFrame 函数应用和映射
  11. 526个儿童游戏APP应用音效游戏声音集合音效素材 Kids Game Sound Effects
  12. 【学术分享】论文投稿被拒2次,再找第三家的时候突然想放弃怎么办?
  13. MPB:中科院微生物所蔡磊组-​基于扩增子数据的系统发育树的构建和展示
  14. ps不更改原图比例,调整图片至任意尺寸
  15. GMT和UTC时区概念
  16. 【C语言】函数详解第一期,函数基础
  17. Qt|layout布局相关,layout属性的含义及使用
  18. 2000个工作汇报PPT模板免费下载
  19. 华为路由器时间同步_华为NTP配置实例
  20. 2021年起重机司机(限门式起重机)考试及起重机司机(限门式起重机)找解析

热门文章

  1. Adobe国际认证|Adobe Stock 2022 年创意趋势预测
  2. 解决mathtype中公式粘贴到word中后公式与文字不对齐等问题
  3. STM32按键控制开关灯
  4. 校园商铺-4-店铺注册功能模块
  5. foreach循环遍历数组方法vue介绍
  6. 基于模型的航电系统测试在空客的应用
  7. ubuntu开机黑屏,左上角光标闪烁
  8. redis和memcached的区别和使用场景
  9. ios分屏_【资讯】前iOS设计师主刀?vivo手机新系统发布在即!
  10. html5 移动端单页面布局,移动端单页布局-如何更好的自适应各尺寸屏幕