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 使用的機會不多,且實際應用相對麻煩,所以不再詳細說明