1. 程式人生 > 其它 >Android 動畫

Android 動畫

Android的動畫分為了三種, 分別是 幀動畫、View動畫(補間動畫)、屬性動畫。

1、幀動畫

幀動畫就是順序播放一組預先定義好的圖片,就類似於我們觀看視訊,就是一張一張的圖片連續播放。

幀動畫的使用很簡單,總共就兩個步驟:

  • 1、在res/drawable目錄下定義一個XML檔案,根節點為系統提供的animation-list,然後放入定義更好的圖片;
  • 2、使用AnimationDrawable類播放第一步定義好的Drawable中的圖片,形成動畫效果;

程式碼示例,第一步,建立Drawable檔案,放在res/rawable目錄下:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
	android:oneshot="false">
	<item android:drawable="@drawable/image01" android:duration="500"/>
	<item android:drawable="@drawable/image02" android:duration="500"/>
	<item android:drawable="@drawable/image03" android:duration="500"/>
</animation-list>

上述xml中,有些屬性我們要了解到:

  • 1、android:oneshot=“false”: 表示是否重複播放動畫,還是隻播放一次;
  • 2、每個item都有Drawable和duration屬性,Drawable表示我們要播放的圖片;duration表示這張圖播放的時間;

程式碼示例,第二步,用AnimationDrawable播放動畫:

    Button button = (Button) findViewById(R.id.bt_001);
    button.setBackgroundResource(R.drawable.frame_animation);//把Drawable設定為button的背景
    //拿到這個我們定義的Drawable,實際也就是AnimationDrawable
    AnimationDrawable animationDrawable = (AnimationDrawable) button.getBackground();
    animationDrawable.start();//開啟動畫

2、View動畫(也稱補間動畫)

2.1 View動畫的基本介紹

view動畫也稱為補間動畫,因為我們只需要拿到一個view,設定它開始和結束的位置,中間的view會自動由系統補齊,而不需要幀動畫每一幅圖都是提前準備好的。

View動畫是Android一開始就提供的比較原始的動畫,主要支援四種效果:平移、縮放、旋轉、透明度變化(漸變) 四種基本效果,我們可以再這四種基礎效果的基礎上,選擇其中的幾種進行組合。

View動畫的四種基本效果對應了四個Animation的子類,如下:

在這裡插入圖片描述
比如建立一個平移動畫translate_animation.xml, 也是需要把xml檔案放在res/anim目錄下:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="100"
    android:fromYDelta="0"
    android:toXDelta="0"
    android:toYDelta="0"/>

scale_animation.xml :

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromXScale="0.0"
    android:fromYScale="0.0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toXScale="1.0"
    android:toYScale="1.0"/>

pivotX和pivotY表示以縮放中心的位置。

rotate_animation.xml:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
      android:fromDegree="0"
      android:toDegree="1800"
      android:pivotX = "50%"
      android:pivotY="50%"
      android:duration = "3000"
/>

漸變動畫alpha_animation.xml:

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromAlpha="1.0"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:toAlpha="0.0" />

interpolator表示動畫插值器, 可以控制動畫的變化速率, 比如前200ms很慢,中間600ms很快,最後200ms又很慢。

pivot 這個屬性主要是在translate 和 scale 動畫中,這兩種動畫都牽扯到view 的“物理位置“發生變化,所以需要一個參考點。而pivotX和pivotY就共同決定了這個點;它的值可以是float或者是百分比數值。
以 pivotX 為例,說明其取不同的值的含義:

  • 10:距離動畫所在view自身左邊緣10畫素
  • 10% :距離動畫所在view自身左邊緣 的距離是整個view寬度的10%
  • 10%p:距離動畫所在view父控制元件左邊緣的距離是整個view寬度的10%

在Activity中使用動畫:

Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.rotate_animation);
textView.startAnimation(animation);

除了用xml來設定View動畫,也可以用程式碼直接搞定,如

Animation translateAnimation = new TranslateAnimation(0,500,0,500);
    // 建立平移動畫的物件:平移動畫對應的Animation子類為TranslateAnimation
    // 引數分別是:
    // 1. fromXDelta :檢視在水平方向x 移動的起始值
    // 2. toXDelta :檢視在水平方向x 移動的結束值
    // 3. fromYDelta :檢視在豎直方向y 移動的起始值
    // 4. toYDelta:檢視在豎直方向y 移動的結束值
    translateAnimation.setDuration(3000);
    // 播放動畫直接 startAnimation(translateAnimation)
    //如:
    mButton.startAnimation(translateAnimation);

2.2 View動畫的組合動畫–AnimationSet

我們可以使用AnimationSet把View動畫的平移、縮放、旋轉、漸變都揉在一起,也是既能通過程式碼實現,也可以通過xml實現

xml實現:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
 android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    >
    <scale
        android:duration="3000"
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0"/>
    <alpha
        android:duration="3000"
        android:fromAlpha="1.0"
        android:toAlpha="0.5" />
    <rotate
        android:fromDegrees="0"
        android:toDegrees="720"
        android:pivotX = "50%"
        android:pivotY="50%"
        android:duration = "3000"
        />
    <translate
        android:fromXDelta="0"
        android:toXDelta="100"
        android:fromYDelta="0"
        android:toYDelta="100" />
</set>

程式碼實現:

AnimationSet setAnimation = new AnimationSet(true);
    // 特別說明以下情況
    // 因為在下面的旋轉動畫設定了無限迴圈(RepeatCount = INFINITE)
    // 所以動畫不會結束,而是無限迴圈
    // 所以組合動畫的下面兩行設定是無效的, 以後設定的為準
    setAnimation.setRepeatMode(Animation.RESTART);
    setAnimation.setRepeatCount(1);// 設定了迴圈一次,但無效

    // 旋轉動畫
    Animation rotate = new RotateAnimation(0,360,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
    rotate.setDuration(1000);
    rotate.setRepeatMode(Animation.RESTART);
    rotate.setRepeatCount(Animation.INFINITE);

    // 平移動畫
    Animation translate = new TranslateAnimation(TranslateAnimation.RELATIVE_TO_PARENT,-0.5f,
            TranslateAnimation.RELATIVE_TO_PARENT,0.5f,
            TranslateAnimation.RELATIVE_TO_SELF,0
            ,TranslateAnimation.RELATIVE_TO_SELF,0);
    translate.setDuration(10000);

    // 透明度動畫
    Animation alpha = new AlphaAnimation(1,0);
    alpha.setDuration(3000);
    alpha.setStartOffset(7000);

    // 縮放動畫
    Animation scale1 = new ScaleAnimation(1,0.5f,1,0.5f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
    scale1.setDuration(1000);
    scale1.setStartOffset(4000);

    // 將建立的子動畫新增到組合動畫裡
    setAnimation.addAnimation(alpha);
    setAnimation.addAnimation(rotate);
    setAnimation.addAnimation(translate);
    setAnimation.addAnimation(scale1);
    // 使用
    mButton.startAnimation(setAnimation);

2.3 View動畫的使用場景

場景一:LayoutAnimation

LayoutAnimation作用於ViewGroup,為ViewGroup指定一個動畫,然後,當它的子元素出場時都會具有這種效果。這種效果常用與ListView,有的ListView的每個item都以一定的動畫形式出現,就是用到的LayoutAnimation。

LayoutAnimation也是一個View動畫, 使用方式有三步:

  • 1、定義LayoutAnimation的xml檔案;
  • 2、指定具體的入場動畫;
  • 3、為ViewGroup指定android:layoutAnimation屬性,引用這個LayoutAnimation的xml檔案;

第一步,定義LayoutAnimation的xml檔案:

// res/anim/anim_layout.xml
<layoutAnimation
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:delay="0.5"
	android:animationOrder="normal"
	android:animation="@anim/anim_item"/>

其中animationOrder有三種選項: normal、reverse、random。

第二步,指定具體動畫,也就是第一步中引用的anim_item:

// res/anim/anim_item.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
	android:duration="300"
	android:interpolator="@android:anim/accelerate_interpolator"
	android:shareInterpolator="true" >
	<alpha
	android:fromAlpha="0.0"
	android:toAlpha="1.0" />
	<translate
	android:fromXDelta="500"
	android:toXDelta="0" />
</set>

第三步,為ViewGroup指定android:layoutAnimation屬性:

<ListView
	android:id="@+id/list"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:layoutAnimation="@anim/anim_layout"
	android:background="#fff4f7f9"
	android:cacheColorHint="#00000000"
	android:divider="#dddbdb"
	android:dividerHeight="1.0px"
	android:listSelector="@android:color/transparent" />

這樣,ListView的每個item都具有了動畫效果。

除了用xml檔案,也同樣可以使用程式碼實現, 程式碼需要用到LayoutAnimationController:

ListView listView = (ListView) layout.findViewById(R.id.list);
Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_
item);
LayoutAnimationController controller = new LayoutAnimationController
(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(controller);

2.4動畫的監聽

Animation.addListener(new AnimatorListener() {
      @Override
      public void onAnimationStart(Animation animation) {
          //動畫開始時執行
      }

       @Override
      public void onAnimationRepeat(Animation animation) {
          //動畫重複時執行
      }

     @Override
      public void onAnimationCancel()(Animation animation) {
          //動畫取消時執行
      }

      @Override
      public void onAnimationEnd(Animation animation) {
          //動畫結束時執行
      }
  });

場景二:Activity的切換效果

Activity有預設的切換效果,但是我們可以定製,主要用到overridePendingTransition(int enterAnima, int exitAnima)這個方法:

Intent intent = new Intent(this,TestActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);

注意, 這個方法必須在startActivity或者finish方法之後呼叫才會生效。

場景三:Fragment的切換效果

可以使用FragmentTransaction的setCustomAnimation方法新增切換動畫。

3、屬性動畫

屬性動畫可以看作是增強版的補間動畫,與補間動畫的不同之處體現在:

  • 補間動畫只能定義兩個關鍵幀在透明、旋轉、位移和傾斜這四個屬性的變換,但是屬性動畫可以定義任何屬性的變化。
  • 補間動畫只能對 UI 元件執行動畫,但屬性動畫可以對任何物件執行動畫。

與補間動畫類似的是,屬性動畫也需要定義幾個方面的屬性:

  • 動畫持續時間。預設為 300ms,可以通過 android:duration 屬性指定。
  • 動畫插值方式。通過 android:interploator 指定。
  • 動畫重複次數。通過 android:repeatCount 指定。
  • 重複行為。通過 android:repeatMode 指定。
  • 動畫集。在屬性資原始檔中通過 <set …/> 來組合。
  • 幀重新整理率。指定多長時間播放一幀。預設為 10 ms。

屬性動畫 API

  • Animator: 提供建立屬性動畫的基類,基本不會直接使用這個類。
  • ValueAnimator:屬性動畫用到的主要的時間引擎,負責計算各個幀的屬性值,基本上其他屬性動畫都會直接或間接繼承它;
  • ObjectAnimator: ValueAnimator 的子類,對指定物件的屬性執行動畫。
  • AnimatorSet:Animator 的子類,用於組合多個 Animator。

除了這些 API,屬性動畫還提供了一個 Evaluator ,用來控制屬性動畫如何計算屬性值。

  • IntEvaluator:計算 int 型別屬性值的計算器。
  • FloatEvaluator: 用於計算 float 型別屬性值的計算器。
  • ArgbEvaluator: 用於計算十六進位制形式表示的顏色值的計算器。
  • TypeEvaluator: 可以自定義計算器。

使用 ValueAnimator 建立動畫的步驟:

  • 呼叫 ValueAnimator 的 ofInt()、ofFloat() 或者 ofObject() 靜態方法建立 ValueAnimator 例項。
  • 呼叫 ValueAnimator 的 setXxx() 等方法設定持續時間,插值方式、重複次數等。
  • 呼叫 ValueAnimator 的 start() 方法啟動動畫。
  • 為 ValueAnimator 註冊 AnimatorUpdateListener 監聽器,在該監聽器中可以監聽 ValueAnimator 計算出來的值改變,並將這些值應用到指定物件上。

屬性動畫的一般使用:

定義屬性動畫和補間動畫等類似,有兩種方式

  • 使用 ValueAnimator 或者 ObjectAnimator 的靜態工廠方法建立動畫。
  • 使用資原始檔來定義動畫。

屬性動畫的使用:

  • 建立 ValueAnimator 或 ObjectAnimator 物件 —— 即可以從 XML 資原始檔載入該動畫也可以直接呼叫 ValueAnimator 或者 ObjectAnimator 的靜態工廠方法建立動畫。
  • 根據需要為 Animator 物件設定屬性。
  • 如果需要監聽 Animator 的動畫開始事件,動畫結束事件、動畫重複事件、動畫值改變事件,並根據事件提供響應處理程式碼,需要為Animator 物件設定監聽器。
  • 如果有多個動畫需要同時播放,需要使用 AnimatorSet 組合這些動畫。
  • 呼叫 Animator 物件的 start 啟動動畫。

程式碼示例:

private void startAnim() {
    ObjectAnimator animator0 = ObjectAnimator.ofFloat(
            mImageViews.get(0),//這裡傳入的是一個任意物件,此處是imageview物件
            "alpha",
            1F,
            0.5F);
    ObjectAnimator animator1 = ObjectAnimator.ofFloat(
            mImageViews.get(1),
            "translationY",
            200F);
    ObjectAnimator animator2 = ObjectAnimator.ofFloat(
            mImageViews.get(2),
            "translationX",
            200F);
    ObjectAnimator animator3 = ObjectAnimator.ofFloat(
            mImageViews.get(3),
            "translationY",
            -200F);
    ObjectAnimator animator4 = ObjectAnimator.ofFloat(
            mImageViews.get(4),
            "translationX",
            -200F);
    AnimatorSet set = new AnimatorSet();
    set.setDuration(500);
    set.setInterpolator(new BounceInterpolator());
    set.playTogether(
            animator0,
            animator1,
            animator2,
            animator3,
            animator4);
    set.start();
    mFlag = false;
}