Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 屬性動畫Property Animation

Android 屬性動畫Property Animation

編輯:關於Android編程

1、概述 Android提供了幾種動畫類型:View Animation 、Drawable Animation 、Property Animation 。View Animation相當簡單,可以支持簡單的縮放、平移、旋轉、透明度基本的動畫。Drawable Animation分為逐幀動畫和補間動畫。Property Animation的功能可以說是最強大的(從某種角度看,屬性動畫是補間動畫的增強版),屬性動畫需要定義如下幾方面屬性:
  • 動畫持續時間:該屬性的默認值是300毫秒。在屬性動畫資源文件中通過android:duration屬性指定。
  • 動畫差值方式:該屬性的作用與補間動畫中差值屬性的作用基本類似,用來定義動畫的變化率。在屬性動畫資源文件中通過android:interpolator屬性指定。
  • 動畫重復次數:指定動畫重復播放的次數,在屬性動畫資源文件中通過android:repeatCount屬性指定。
  • 動畫重復模式:指定動畫播放結束後、下次播放時,是從開始幀再次播放到結束幀,還是從結束幀反向播放到開始幀。在屬性動畫資源文件中通過android:repeatMode屬性指定。
  • 動畫集:將多個屬性動畫合並成一組,既可以讓這組屬性動畫按次序播放,也可以讓這組動畫同時播放,在屬性動畫資源文件中通過元素來組合。
  • 幀刷新頻率:指定每隔多長時間播放一幀,默認值是10毫秒。   2、相關API
  • Animator:它提供了創建屬性動畫的基類,基本上不會直接使用該類,通常要繼承它並重寫想方法。
  • ValueAnimator :屬性動畫主要的時間引擎,它負責計算各個幀的屬性值。它定義了屬性動畫的絕大部分核心功能:計算各幀的相關屬性值,負責處理更新事件,按屬性值的類型控制計算規則。屬性動畫主要由兩方面組成:1、計算各幀的相關屬性值;2、為指定對象設置這些計算後的值。ValueAnimator只負責第一部分,所以程序員必須根據ValueAnimator計算並監聽值更新來更新對象的相關屬性值。
  • ObjectAnimator:它是ValueAnimator子類,運行對指定對象的屬性執行動畫。
  • AnimatorSet:它是Animator子類,用於組合多個Animator,並指定它們的播放次序。 同時,屬性動畫還需要利用一個Evaluator(計算器),該工具類控制屬性動畫如何計算屬性值,共有如下幾種Evaluator:
  • IntEvaluator:用於計算int型屬性值;
  • FloatEvaluator:用於計算float型屬性值;
  • IntEvaluator:用於計算以16進制形式表示的顏色值;
  • TypeEvaluator:計算器接口,可以通過實現該接口類來實現自定義計算器。
  3、使用ValueAnimator實現動畫
  • 使用ValueAnimator動畫可按如下步驟:
  • 調用ValueAnimator的ofInt()、ofFloat()或ofObject()方法創建ValueAnimator實例。
  • 調用ValueAnimator的setXxx()方法設置動畫持續時間、差值方式、重復次數等。
  • 調用ValueAnimator的start()方法啟動動畫。
  • 為ValueAnimator注冊AnimatorUpdateListener監聽器,在監聽器中監聽ValueAnimator變化的值,並將這些值應用到指定對象。
看個例子:
animator = ValueAnimator.ofFloat(0f, 300);
animator.setDuration(4000);
animator.start();
這段代碼僅僅是計算了動畫變化過程值,並沒有把值應用到任何對象上,如何要顯示出效果,還要注冊一個監聽器——AnimatorUpdateListener,通過getAnimatedValue()方法獲取當前幀的值,並將該值應用到指定對象上:
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mImageView.setTranslationX( (Float)animation.getAnimatedValue());
}
});

 

效果如下:
\ 當然,我們也可以自定義一個Evaluator計算器,例如:
animator=ValueAnimator.ofObject(new CustomEvaluatour(), startVal,endVal);
animator.setDuration(1000);
animator.start();
4、使用ObjectAnimator創建動畫 ObjectAnimator繼承ValueAnimator,因此可以它能夠直接將ValueAnimator在動畫過程中計算出來的值應用到指定屬性上,所以使用ObjectAnimator就不需要注冊AnimatorUpdateListener監聽器了,下面我就以鴻洋大神的例子作為說明了 布局文件如下:
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >

android:onClick="changeAlpha"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/circle_photo" />
Activity代碼:
public class ObjectAnimatorActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_object_animator);
}

public void changeAlpha(final View view) {
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", 1.0F, 0.2F)
.setDuration(500);//
anim.start();
}
}
效果如下:
\ 與ValueAnimator不同的是,我們在使用ObjectAnimator還要注意以下幾點:
  • 如果調用了ObjectAnimator提供的ofInt()、ofFloat()或ofObject()方法,這幾個方法都是設置動畫作用的元素、作用的屬性、動畫開始、結束、以及中間的任意個屬性值。當對於屬性值,只設置一個的時候(通常需要開始值和結束值),該值會被認為是結束值,當前對象該屬性的值為開始值(getPropName反射獲取)。該對象應該為該屬性提供一個getter方法,getter的返回值作為開始值。
  • 如果操作對象的該屬性方法裡面,比如上例的setAlpha(),如果內部沒有調用view的重繪,則還需要在onAnimationUpdate()事件監聽方法中調用View.invalidate()來刷新屏幕的顯示:
anim.addUpdateListener(newAnimatorUpdateListener()
{
@Override
publicvoidonAnimationUpdate(ValueAnimatoranimation)
{
//view.postInvalidate();
//view.invalidate();
}
});
  上面的例子,設置的操作的屬性只有一個,如果希望一個動畫能夠讓一個View支持多個動畫怎麼辦?可能會說使用AnimatorSet就行了,但是只使用ObjectAnimator能否實現呢?下面實現下:
public void changeAlpha(final View view) {
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "xmr", 1.0F, 0.2F)
.setDuration(5000);
anim.start();

anim.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
float value = (Float) animation.getAnimatedValue();
view.setAlpha(value);
view.setScaleX(value);
view.setScaleY(value);
}
});
}
因為我們要在下面設置透明度,所以把設置屬性的那個字符串“alpha"隨便改一個該對象沒有的屬性,只需要它按照時間插值和持續時間計算的那個值,自己手動調用即可: \   實際上使用propertyValuesHolder也可以實現一個動畫更改多個效果:
public void changeAlpha(View view)
{
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,
0f, 1f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f,
0, 1f);
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f,
0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration(5000).start();
}

 

5、監聽動畫的事件 動畫一般都是做一些輔助效果,比如我要刪除個元素,我可能希望是個淡出的效果,但是最終還是要刪處,並不是你透明度沒有了,還占著位置,所以我們需要知道動畫如何結束。 所以我們可以添加一個動畫的監聽:
ublic void fadeOut(View view) {
ObjectAnimator anim = ObjectAnimator.ofFloat(mImageView, "alpha", 0.5f)
.setDuration(5000);
anim.start();

anim.addListener(new AnimatorListener() {

@Override
public void onAnimationStart(Animator animation) {
}

@Override
public void onAnimationRepeat(Animator animation) {
}

@Override
public void onAnimationEnd(Animator animation) {
ViewGroup parent = (ViewGroup) mImageView.getParent();
if (parent != null)
parent.removeView(mImageView);
}

@Override
public void onAnimationCancel(Animator animation) {
}
});
}

 

這個監聽器可以監聽動畫的開始、結束、被取消、重復等事件,但是有時候只要知道結束就行了,那你可以使用AnimatorListenerAdapter,AnimatorListenerAdapter繼承了AnimatorListener接口,然後空實現了所有的方法:
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
ViewGroup parent = (ViewGroup) mImageView.getParent();
if (parent != null)
parent.removeView(mImageView);
}
});

 

\ 6、AnimatorSet的使用 布局文件:
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >

android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="togetherRun"
android:text="多動畫同時執行" />

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="playWithAfter"
android:text="多動畫按次序執行" />


android:id="@+id/iv_anim"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/circle_photo" />
  代碼:
public class AnimatorSetActivity extends Activity {
private ImageView mImageView;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animator_set);

mImageView = (ImageView) findViewById(R.id.iv_anim);

}

public void togetherRun(View view)
{
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mImageView, "scaleX",
1.0f, 2.0f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mImageView, "scaleY",
1.0f, 2.0f);

AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(5000);
animSet.setInterpolator(new LinearInterpolator());
//兩個動畫同時執行
animSet.playTogether(anim1, anim2);
// animSet.playSequentially(items)
animSet.start();
}

public void playWithAfter(View view)
{
float cx = mImageView.getX();

ObjectAnimator anim1 = ObjectAnimator.ofFloat(mImageView, "scaleX",
1.0f, 2.0f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mImageView, "scaleY",
1.0f, 2.0f);
ObjectAnimator anim3 = ObjectAnimator.ofFloat(mImageView,
"x", cx , 0.0f);
ObjectAnimator anim4 = ObjectAnimator.ofFloat(mImageView,
"x", cx);

/**
* anim1,anim2,anim3同時執行
* anim4接著執行
*/
AnimatorSet animSet = new AnimatorSet();
animSet.play(anim1).with(anim2);
animSet.play(anim2).with(anim3);
animSet.play(anim4).after(anim3);
animSet.setDuration(2000);
animSet.start();
}
}

 

效果如下:
\ 有一點注意:animSet.play().with();也是支持鏈式編程的,但是不要想著狂點,比如 animSet.play(anim1).with(anim2).before(anim3).before(anim5); 這樣是不行的,系統不會根據你寫的這一長串來決定先後的順序,所以麻煩你按照上面例子的寫法,多寫幾行 好了,先說這麼多吧

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved