Android動畫基本上可以分為視圖動畫和屬性動畫,視圖動畫包括幀動畫和補間動畫。
一.概述
通過本篇文章的學習,你將學會:
1.如何使用幀動畫
2.如何使用補間動畫
3.如何使用屬性動畫
二.幀動畫
幀動畫就是按照順序播放一幀一幀的照片達到動畫的效果。我們可以看一下實現(xiàn)過程:
在drawable目錄下新建frame_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item
android:drawable="@mipmap/a_0"
android:duration="100" />
<item
android:drawable="@mipmap/a_1"
android:duration="100" />
<item
android:drawable="@mipmap/a_2"
android:duration="100" />
</animation-list>
<!--oneshot表示是否只播放一次,默認false-->
在activity用兩個按鈕來啟動動畫和暫停動畫:
Button bt_start, bt_stop;
ImageView iv;
AnimationDrawable animationDrawable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_frame);
bt_start = (Button) findViewById(R.id.bt_start);
bt_stop = (Button) findViewById(R.id.bt_stop);
iv = (ImageView) findViewById(R.id.iv);
iv.setImageResource(R.drawable.frame_list);
animationDrawable = (AnimationDrawable) iv.getDrawable();
bt_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//啟動幀動畫
animationDrawable.start();
}
});
bt_stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//暫停幀動畫
animationDrawable.stop();
}
});
}
幀動畫使用簡單方便,但是注意在比較復雜的時候圖片比較多的時候容易發(fā)生oom,因此盡量避免使用尺寸較大的圖片。
三.補間動畫
補間動畫是通過確定視圖開始和結束的樣式,然后中間的樣式由系統(tǒng)進行補全形成。但是它只是去改變了視覺效果,并不會改變控件本身的屬性。補間動畫包括基本的平移動畫,縮放動畫,旋轉動畫和透明度動畫,我們也可以將這些基本動畫進行組合在一起。
所有的補間動畫共有的屬性:
duration:動畫時長
startOffset:動畫延遲開始時間
fillAfter:動畫結束后是否停留在結束狀態(tài)
repeatMode:重復播放動畫模式restart代表正序重放,reverse代表倒序回放
repeatCount:重放次數(shù)(+1),為infinite時無限重復
interpolator:插值器:選擇動畫變化的模式,有勻速,加速,減速,先加速在減速。。。
平移動畫
平移動畫有其特有的屬性,平移動畫在水平方向初始值和結束值,在豎直方向的初始值和結束值
有兩種方式實現(xiàn)平移動畫:
- xml形式:
1.在res目錄下新建anim文件夾,創(chuàng)建animation_translate.xml:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:startOffset ="1000"
android:fillAfter = "false"
android:repeatMode= "reverse"
android:repeatCount = "infinite"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXDelta="0"
android:toXDelta="500"
android:fromYDelta="0"
android:toYDelta="0">
<!--duration:動畫時長
startOffset:動畫延遲開始時間
fillAfter:動畫結束后是否停留在結束狀態(tài)
repeatMode:重復播放動畫模式restart代表正序重放,reverse代表倒序回放
repeatCount:重放次數(shù)(+1),為infinite時無限重復
interpolator:插值器:選擇動畫變化的模式,有勻速,加速,減速,先加速在減速。。。
以上是所有補間動畫共有的屬性,以下是平移動畫特有的屬性
fromXDelta:平移動畫在水平方向x初始值
toXDelta:平移動畫在水平方向x結束值
fromYDelta:平移動畫在豎直方向y初始值
toYDelta:平移動畫在豎直方向y結束值-->
</translate>
各個參數(shù)的意義在xml文件中已注明
2.通過AnimationUtils.loadAnimation方法獲取Animation對象讓控件開始動畫:
Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation_translate);
bt_translate.startAnimation(animation);
- java動態(tài)執(zhí)行動畫:
//分別對應xml中的fromXDelta,toXDelta,fromYDelta,toYDelta
Animation animation2 = new TranslateAnimation(0, 500, 0, 500);
animation2.setStartOffset(1000);//動畫延遲開始時間
animation2.setDuration(3000);//動畫持續(xù)時長
bt_translate2.startAnimation(animation2);
注意:兩種方式都一定需要有duration屬性設置動畫時長,否則動畫不起作用
縮放動畫
縮放動畫有其特有的屬性,縮放動畫在水平方向起始縮放倍數(shù)和結束縮放倍數(shù),在豎直方向的初始縮放倍數(shù)和結束縮放倍數(shù)
有兩種方式實現(xiàn)縮放動畫:
- xml形式:
1.在res的anim目錄下創(chuàng)建animation_scale.xml:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:startOffset ="1000"
android:fillAfter = "false"
android:repeatMode= "reverse"
android:repeatCount = "infinite"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="0"
android:toXScale="2"
android:fromYScale="1"
android:toYScale="1"
android:pivotX="50%"
android:pivotY="50%">
<!--fromXScale:動畫在水平方向X的起始縮放倍數(shù)
fromYScale:動畫在豎直方向Y的起始縮放倍數(shù)
pivotX:縮放軸點的x坐標
pivotY:縮放軸點的y坐標
pivotX pivotY,可取值為數(shù)字,百分比,或者百分比p
設置為數(shù)字時(如50),軸點為View的左上角的原點在x方向和y方向加上50px的點。在Java代碼里面設置這個參數(shù)的對應參數(shù)是Animation.ABSOLUTE。
設置為百分比時(如50%),軸點為View的左上角的原點在x方向加上自身寬度50%和y方向自身高度50%的點。在Java代碼里面設置這個參數(shù)的對應參數(shù)是Animation.RELATIVE_TO_SELF。
設置為百分比p時(如50%p),軸點為View的左上角的原點在x方向加上父控件寬度50%和y方向父控件高度50%的點。在Java代碼里面設置這個參數(shù)的對應參數(shù)是Animation.RELATIVE_TO_PARENT-->
</scale>
各個參數(shù)的意義在xml文件中已注明
2.通過AnimationUtils.loadAnimation方法獲取Animation對象讓控件開始動畫:
Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation_scale);
bt_scale1.startAnimation(animation);
- java動態(tài)執(zhí)行動畫:
//參數(shù)分別對應fromXScale,toXScale,fromYScale,toYScale,縮放軸點X坐標類型,pivotX,縮放軸點Y坐標類型,pivotY
Animation animation2 = new ScaleAnimation(0, 2, 0, 2, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation2.setStartOffset(1000);
animation2.setDuration(3000);
bt_scale2.startAnimation(animation2);
注意:兩種方式都一定需要有duration屬性設置動畫時長,否則動畫不起作用
旋轉動畫
旋轉動畫有其特有的屬性,旋轉動畫在動畫開始時視圖的旋轉角度,在動畫結束時視圖的旋轉角度
有兩種方式實現(xiàn)縮放動畫:
- xml形式:
1.在res的anim目錄下創(chuàng)建animation_rotate.xml:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:startOffset ="1000"
android:fillAfter = "false"
android:repeatMode= "reverse"
android:repeatCount = "infinite"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%">
<!--fromDegrees:動畫開始時 視圖的旋轉角度 正數(shù) = 順時針,負數(shù) = 逆時針
toDegrees:動畫結束時 視圖的旋轉角度
pivotX:旋轉軸點的x坐標
pivotY:旋轉軸點的y坐標
pivotX pivotY,可取值為數(shù)字,百分比,或者百分比p
設置為數(shù)字時(如50),軸點為View的左上角的原點在x方向和y方向加上50px的點。在Java代碼里面設置這個參數(shù)的對應參數(shù)是Animation.ABSOLUTE。
設置為百分比時(如50%),軸點為View的左上角的原點在x方向加上自身寬度50%和y方向自身高度50%的點。在Java代碼里面設置這個參數(shù)的對應參數(shù)是Animation.RELATIVE_TO_SELF。
設置為百分比p時(如50%p),軸點為View的左上角的原點在x方向加上父控件寬度50%和y方向父控件高度50%的點。在Java代碼里面設置這個參數(shù)的對應參數(shù)是Animation.RELATIVE_TO_PARENT-->
</rotate>
各個參數(shù)的意義在xml文件中已注明
2.通過AnimationUtils.loadAnimation方法獲取Animation對象讓控件開始動畫:
Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation_rotate);
bt_rotate1.startAnimation(animation);
- java動態(tài)執(zhí)行動畫:
//參數(shù)分別對應fromDegrees,toDegrees,旋轉軸點X坐標類型,pivotX,旋轉軸點Y坐標類型,pivotY
Animation animation2 = new RotateAnimation(0, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation2.setStartOffset(1000);
animation2.setDuration(3000);
bt_rotate2.startAnimation(animation2);
注意:兩種方式都一定需要有duration屬性設置動畫時長,否則動畫不起作用
透明度動畫
透明度動畫有其特有的屬性,透明度動畫在動畫開始時視圖的初始透明度,在動畫結束時視圖的結束透明度
有兩種方式實現(xiàn)透明度動畫:
- xml形式:
1.在res的anim目錄下創(chuàng)建animation_alpha.xml:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:startOffset ="1000"
android:fillAfter = "false"
android:repeatMode= "reverse"
android:repeatCount = "infinite"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromAlpha="0"
android:toAlpha="1">
<!--fromAlpha:動畫開始時視圖的初始透明度
toAlpha:動畫結束時視圖的結束透明度-->
</alpha>
各個參數(shù)的意義在xml文件中已注明
2.通過AnimationUtils.loadAnimation方法獲取Animation對象讓控件開始動畫:
Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation_alpha);
bt_alpha1.startAnimation(animation);
- java動態(tài)執(zhí)行動畫:
//參數(shù)分別對應fromAlpha,toAlpha
Animation animation2 = new AlphaAnimation(0, 1);
animation2.setStartOffset(1000);
animation2.setDuration(3000);
bt_alpha2.startAnimation(animation2);
注意:兩種方式都一定需要有duration屬性設置動畫時長,否則動畫不起作用
組合動畫
組合動畫就是將上面的四種動畫組合在一起,同事?lián)碛衅揭?,縮放,旋轉和透明度變化的動畫。同樣有兩種方式:
- xml形式:
1.在res目錄下新建anim文件夾,創(chuàng)建animation_set.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="1000"
android:fromAlpha="0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toAlpha="1" />
<translate
android:duration="2000"
android:fromXDelta="0"
android:fromYDelta="0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:startOffset="3000"
android:toXDelta="500"
android:toYDelta="0" />
<rotate
android:duration="3000"
android:fromDegrees="0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:repeatMode="restart"
android:toDegrees="360" />
<scale
android:duration="3000"
android:fromXScale="1"
android:fromYScale="1"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="4000"
android:toXScale="0.5"
android:toYScale="0.5" />
</set>
2.通過AnimationUtils.loadAnimation方法獲取Animation對象讓控件開始動畫:
Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation_set);
bt_animation1.startAnimation(animation);
- java動態(tài)執(zhí)行動畫:
//動態(tài)
bt_animation2 = (Button) findViewById(R.id.bt_animation2);
AnimationSet animationSet = new AnimationSet(true);
//子動畫一
Animation animation1 = new AlphaAnimation(0, 1);
animation1.setDuration(1000);
//子動畫二
Animation animation2 = new TranslateAnimation(0, 500, 0, 0);
animation2.setDuration(2000);
animation2.setStartOffset(3000);
//子動畫三
Animation animation3 = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation3.setDuration(3000);
animation3.setRepeatMode(Animation.RESTART);
animation3.setRepeatCount(Animation.INFINITE);
//子動畫四
Animation animation4 = new ScaleAnimation(1, 0.5f, 1, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation4.setDuration(3000);
animation4.setStartOffset(4000);
animationSet.addAnimation(animation1);
animationSet.addAnimation(animation2);
animationSet.addAnimation(animation3);
animationSet.addAnimation(animation4);
bt_animation2.startAnimation(animationSet);
這樣就能實現(xiàn)組合動畫。
動畫監(jiān)聽
通過setAnimationListener得到動畫監(jiān)聽回調,開始和結束
animation2.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
四.屬性動畫
我們知道幀動畫和補間動畫都只是改變視覺效果,并沒有真正改變控件的屬性,因此我們接觸到了屬性動畫,屬性動畫中一些類的繼承關系如下:

我們可以著重看到ValueAnimator,ObjectAnimator和AnimatorSet三個類,因此,屬性動畫主要圍繞這三個類展開,看看屬性動畫是怎么實現(xiàn)的。
ValueAnimator
通過不斷控制值的變化,變化過程中再不斷手動賦給對象的屬性,從而實現(xiàn)動畫效果。
它有三個主要的方法:ValueAnimator.ofInt(int values),ValueAnimator.oFloat(float values)和ValueAnimator.ofObject()。
1.ValueAnimator.ofInt(int values):
它的參數(shù)可以傳入多個int值,表示多個int值之間進行一個平滑過渡,得到一個動畫實例,通過動畫的更新監(jiān)聽器將平滑過渡的值傳給控件來改變控件的屬性打到動畫效果。
縮放效果:
bt_value1 = (Button) findViewById(R.id.bt_value1);
//步驟1.創(chuàng)建動畫實例,將傳入的多個Int參數(shù)進行平滑過渡,這里只有兩個int參數(shù),可以有多個
ValueAnimator valueAnimator = ValueAnimator.ofInt(bt_value1.getLayoutParams().width, 500);
//步驟2.設置動畫的播放各種屬性,如動畫運行的時長setDuration,動畫延遲播放時間setStartDelay,動畫重復播放次數(shù)setRepeatCount,重復播放動畫模式setRepeatMode
valueAnimator.setDuration(3000);
//步驟3.將改變的值手動賦值給對象的屬性值:通過動畫的更新監(jiān)聽器,值每次改變、變化一次,該方法就會被調用一次
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int currentValue = (int) valueAnimator.getAnimatedValue();
bt_value1.getLayoutParams().width = currentValue;//將當前的值給button作為寬度
bt_value1.requestLayout();//對button進行重新繪制
}
});
//步驟4.開啟動畫
valueAnimator.start();
平移效果:
bt_value2 = (Button) findViewById(R.id.bt_value2);
ValueAnimator valueAnimator2 = ValueAnimator.ofInt(0, 300);
valueAnimator2.setDuration(3000);
valueAnimator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int currentMargin = (int) valueAnimator.getAnimatedValue();
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(bt_value2.getLayoutParams());
layoutParams.setMargins(currentMargin, 0, 0, 0);
bt_value2.setLayoutParams(layoutParams);
}
});
valueAnimator2.start();
透明度效果:
bt_value3 = (Button) findViewById(R.id.bt_value3);
ValueAnimator valueAnimator3 = ValueAnimator.ofFloat(0, 1);
valueAnimator3.setDuration(3000);
valueAnimator3.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float currentValue = (float) valueAnimator.getAnimatedValue();
bt_value3.setAlpha(currentValue);
bt_value3.requestLayout();
}
});
valueAnimator3.start();
接下來主要講一下ValueAnimator.ofObject()方法的使用。
2.ValueAnimator.ofObject(TypeEvaluator evaluator,Object object):
在補間動畫的時候我們有一個interpolator屬性是用來設置插值器的用于設置 屬性值 從初始值過渡到結束值 的變化規(guī)律,諸如減速,加速,勻速,先減速在加速等等這些。該方法的第一個參數(shù)是TypeEvaluator表示的是估值器用于設置 屬性值 從初始值過渡到結束值 的變化具體數(shù)值,也就是根據(jù)時間的進度獲取該方法第二個參數(shù)和第三個參數(shù)在變化過程中的數(shù)值的方法。前面的ofInt是作用于int數(shù)值,ofFloat是作用于Float數(shù)值,所以ofObject是作用于對象,我們先創(chuàng)建一個實例對象Point表示控件距離左側和上側控件的邊距:
public class Point {
// 設置兩個變量用于記錄控件距離左側和上側控件的邊距
private int x;
private int y;
// 構造方法用于設置邊距
public Point(int x, int y) {
this.x = x;
this.y = y;
}
// get方法用于獲取邊距
public int getX() {
return x;
}
public int getY() {
return y;
}
}
然后自定義估值器PointEvaluator用于獲取根據(jù)時間變化過程中的對象objec:
// 實現(xiàn)TypeEvaluator接口
public class PointEvaluator implements TypeEvaluator {
// 復寫evaluate()
// 在evaluate()里寫入對象動畫過渡的邏輯
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
// 將動畫初始值startValue 和 動畫結束值endValue 強制類型轉換成Point對象
Point startPoint = (Point) startValue;
Point endPoint = (Point) endValue;
// 根據(jù)fraction來計算當前動畫的x和y的值
int x = (int) (startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX()));
int y = (int) (startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY()));
// 將計算后的坐標封裝到一個新的Point對象中并返回
Point point = new Point(x, y);
return point;
}
}
我們創(chuàng)建初始對象startPoint和結束對象endPoint,在變化過程中獲取當前point對象并給Button設置距離左側和上側控件的邊距如下:
bt = (Button) findViewById(R.id.bt);
Point startPoint = new Point(0, 0);
Point endPoint = new Point(500, 500);
ValueAnimator valueAnimator = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
valueAnimator.setDuration(3000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
Point currentPoint = (Point) valueAnimator.getAnimatedValue();
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(bt.getLayoutParams());
lp.setMargins(currentPoint.getX(), currentPoint.getY(), 0, 0);
bt.setLayoutParams(lp);
bt.requestLayout();
}
});
valueAnimator.start();
這樣就實現(xiàn)了Button在3秒時間里從startPoint到endPoint邊距的變化過程的動畫,這就是ValueAnimator.ofObject的使用
ObjectAnimator
直接對對象的屬性值進行改變操作,從而實現(xiàn)動畫效果。用法上和ValueAnimator比較類似:
先看下面的對控件進行透明度,平移,縮放和旋轉的動畫:
bt_alpha = (Button) findViewById(R.id.bt_alpha);
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(bt_alpha, "alpha", 0, 1);
objectAnimator.setDuration(3000);
objectAnimator.start();
bt_translate = (Button) findViewById(R.id.bt_translate);
ObjectAnimator.ofFloat(bt_translate, "translationX", bt_translate.getTranslationX(), 300, bt_translate.getTranslationX()).setDuration(3000).start();
bt_scale = (Button) findViewById(R.id.bt_scale);
ObjectAnimator.ofFloat(bt_scale, "scaleX", 0, 2, 1).setDuration(3000).start();
bt_rotate = (Button) findViewById(R.id.bt_rotate);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(bt_rotate, "rotationY", 0, 360).setDuration(3000);
objectAnimator2.setRepeatCount(ValueAnimator.INFINITE);
objectAnimator2.start();
注意上面ObjectAnimator.ofFloat方法中的第二個參數(shù)決定了對控件什么操作,參數(shù)名稱對應作用見下表:
| 屬性 | 作用 | 數(shù)值類型 |
|---|---|---|
| Alpha | 控制View的透明度 | float |
| TranslationX | 控制X方向的位移 | float |
| TranslationY | 控制Y方向的位移 | float |
| ScaleX | 控制X方向的縮放倍數(shù) | float |
| ScaleY | 控制Y方向的縮放倍數(shù) | float |
| Rotation | 控制以屏幕方向為軸的旋轉度數(shù) | float |
| RotationX | 控制以X軸為軸的旋轉度數(shù) | float |
| RotationY | 控制以Y軸為軸的旋轉度數(shù) | float |
注意:ObjectAnimator是對對象的屬性值進行改變操作,那么要動畫生效,必須滿足兩個條件:
1.對象必須要提供屬性a的set()方法,而且如果沒傳遞初始值,那么需要提供get()方法,因為系統(tǒng)要去拿屬性a的初始值
2.屬性a的set()方法 對 屬性a的改變帶來ui上的變化
只有同時滿足上面兩個條件,動畫才會生效。那么如果不滿足上面兩個條件但是想用怎么辦,有兩種方法:
1.通過繼承原始類,直接給類加上該屬性的 get()& set(),從而實現(xiàn)給對象加上該屬性的 get()& set()
2.通過包裝原始動畫對象,間接給對象加上該屬性的 get()&set()。即 用一個類來包裝原始對象。
比如,width這個屬性,雖然控件有set和get的方法,但是控件的set方法并不是設置控件寬度用的,而是設置控件最大寬度和最小寬度的,因此無法去改變控件的寬度,自然動畫無法生效。我們可以使用第二種方法進行包裝來進行動畫改變控件的寬度。先自定義類ViewWrapper添加對View寬度的set個get方法:
public class ViewWrapper {
View view;
public ViewWrapper(View view) {
this.view = view;
}
//得到控件的寬度
public int getWidth() {
return view.getLayoutParams().width;
}
//設置控件的寬度
public void setWidth(int width) {
view.getLayoutParams().width = width;
view.requestLayout();
}
}
在使用ObjectAnimator對ViewWrapper 對象的width屬性進行動態(tài)改變也就改變了控件的寬度從而達到動畫的效果:
bt = (Button) findViewById(R.id.bt);
ViewWrapper viewWrapper = new ViewWrapper(bt);
ObjectAnimator animator = ObjectAnimator.ofInt(viewWrapper, "width", 0, 500);
animator.setDuration(3000);
animator.start();
AnimatorSet
AnimatorSet是組合動畫,畢竟淡一點動畫還是比較少,很多時候動畫都是由單一的屬性動畫組合在一起。AnimatorSet的使用有如下方法:
AnimatorSet.play(Animator anim) :播放當前動畫
AnimatorSet.after(long delay) :將現(xiàn)有動畫延遲delay毫秒后執(zhí)行
AnimatorSet.with(Animator anim) :將現(xiàn)有動畫和傳入的動畫同時執(zhí)行
AnimatorSet.after(Animator anim) :將現(xiàn)有動畫插入到傳入的動畫之后執(zhí)行
AnimatorSet.before(Animator anim) : 將現(xiàn)有動畫插入到傳入的動畫之前執(zhí)行
比如我們需要一個延遲一秒后,先透明度由0-1,然后平移加旋轉加縮放的動畫:
bt2= (Button) findViewById(R.id.bt2);
//子動畫一
ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(bt2,"alpha",0,1);
objectAnimator.setDuration(2000);
//子動畫二
ObjectAnimator objectAnimator2=ObjectAnimator.ofFloat(bt2,"translationX",0,300);
objectAnimator2.setDuration(3000);
//子動畫三
ObjectAnimator objectAnimator3=ObjectAnimator.ofFloat(bt2,"rotation",0,360);
objectAnimator3.setDuration(3000);
//子動畫四
ObjectAnimator objectAnimator4=ObjectAnimator.ofFloat(bt2,"scaleX",1,0.5f);
objectAnimator4.setDuration(3000);
//子動畫五
ObjectAnimator objectAnimator5=ObjectAnimator.ofFloat(bt2,"scaleY",1,0.5f);
objectAnimator5.setDuration(3000);
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.play(objectAnimator2).with(objectAnimator3).with(objectAnimator4).with(objectAnimator5).after(objectAnimator).after(1000);
animatorSet.start();
ViewPropertyAnimator
屬性動畫最終都是對控件的值屬性進行操作,因此,谷歌也開放了直接用控件進行動畫的方法,可以認為是屬性動畫的簡便操作方式:View.animate().xxx();View.animate()返回的是ViewPropertyAnimator,后面調用的方法都是在ViewPropertyAnimator的基礎上進行調用開啟動畫,但是不需要調用start方法去啟動。
bt3 = (Button) findViewById(R.id.bt3);
// bt3.animate().alpha(0).setDuration(3000);//透明度由原來變?yōu)?
// bt3.animate().translationX(300).setDuration(3000);//平移
// bt3.animate().scaleX(0.5f).scaleY(0.5f).setDuration(3000);//X,Y縮放為原來0.5
bt3.animate().rotation(360).setDuration(3000);//順時針旋轉360度
動畫監(jiān)聽
通過addListener添加動畫監(jiān)聽得到動畫開始,結束,取消方法回調
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
當然,可以使用AnimatorListenerAdapter只監(jiān)聽開始或者結束的其中一個方法:
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
});
以上就是屬性動畫相關的用法。
五.總結
以上就是關于Android幀動畫,補間動畫和屬性動畫的相關知識點,如有不足或者錯誤的地方請在下方指正。我們需要多看更需要多寫,只有不斷學習,不斷進步才能不被淘汰。