1. 程式人生 > >Android動畫基礎之補間動畫與逐幀動畫

Android動畫基礎之補間動畫與逐幀動畫

Android動畫分類主要分三類:

  • Tweened Animation補間動畫
  • Frame Animation幀動畫
  • Property Animation屬性動畫

現在我們來介紹一下補間動畫。Tweened Animation補間動畫,是通過配置動畫檔案(xml檔案/Java程式碼)對View的內容進行一系列圖形變換(有平移、縮放、旋轉、透明度)來實現動畫效果。無需逐一定義每一幀,只要定義開始、結束的幀和指定動畫持續時間。

動畫型別 xml標籤配置 Java程式碼實現
漸變透明度 alpha AlphaAnimation
漸變尺寸縮放 scale ScaleAnimation
畫面旋轉 rotate RotateAnimation
畫面位置移動 translate TranslateAnimation
組合動畫 set AnimationSet

XML檔案存放目錄如下:
這裡寫圖片描述

我們首先來介紹一下Animation常用屬性:

Animation.RELATIVE_TO_PARENT 常量以父元件參考定位
Animation.RELATIVE_TO_SELF 常量以自身參考定位
Animation.INFINITE 常量動畫持續重複
Animation.RESTART 常量重新開始動畫
Animation.REVERSE 常量反轉動畫效果
android:duration 一次動畫效果消耗的時間,單位毫秒,值越小動畫速度越快
android:fillAfter 設定為true,表示該動畫轉化在動畫結束後應用
android:fillBefore 設定為true,表示該動畫轉化在動畫開始後應用
android:fillEnable 設定為true,fillAfter、fillBefore才有效
android:repeatCount 表示動畫迴圈的次數,預設為 0 次不迴圈,-1 為無限迴圈。
android:repeatMode 表示是迴圈的模式,reverse 是從一次動畫結束開始,restart 是從動畫的開始處迴圈
android:interpolator 是一個插值器資源,它可以控制動畫的播放速度
android:shareInterpolator 表示是否與 set 中其他動畫共享插值器,false為各自使用各自的插值器
android:startOffset 設定動畫於多少毫秒之後啟動

alpha漸變透明度動畫

下面是AlphaAnimation特用屬性:

android:fromAlpha 表示動畫開始時的透明度
android:toAlpha 表示動畫結束時候的透明度
取值為[0.0,1.0],0代表完全透明,1代表不透明。

xml方式:

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

xml方式載入方式通過AnimationUtils.loadAnimation取得animation物件

        Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_alpha);
        mImageView.startAnimation(animation);

Java程式碼方式:new AlphaAnimation(float fromAlpha, float toAlpha)

        Animation animation = new AlphaAnimation(1.0f, 0.0f);
        animation.setDuration(1000);
        animation.setFillBefore(false);
        mImageView.startAnimation(animation);

scale漸變尺寸縮放動畫

下面是scale縮放動畫屬性:

android:fromXDelta,fromYDelta 起始時X,Y座標
android:toXDelta,toYDelta 動畫結束時X,Y的座標
android:fromXScale,fromYScale 動畫開始前X,Y的縮放,0.0為不顯示, 1.0為正常大小
android:toXScale,toYScale 動畫最終縮放的倍數, 1.0為正常大小,大於1.0放大
android:pivotX,pivotY 動畫起始位置,相對於螢幕的百分比,兩個都為50%表示動畫從自身中間開始

xml方式:

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromXScale="0.5"
    android:fromYScale="0.5"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="1"
    android:repeatMode="reverse"
    android:startOffset="0"
    android:toXScale="2.0"
    android:toYScale="2.0" />

Java方式:new ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)

        Animation animation = new ScaleAnimation(0.5f, 2.0f, 0.5f, 2.0f, 0.5f, 0.5f);
        animation.setDuration(1000);
        animation.setRepeatCount(1);
        animation.setRepeatMode(Animation.REVERSE);
        animation.setStartOffset(0);
        mImageView.startAnimation(animation);

rotate畫面旋轉動畫

我們同樣先介紹rotate的常用屬性:
android:fromDegrees 動畫開始時的角度
android:toDegrees 動畫結束時旋轉角度,正代表順時針
android:pivotX 屬性為動畫相對於元件的X座標的開始位置
android:pivotY 屬性為動畫相對於元件的Y座標的開始位置

xml方式:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromDegrees="0"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="-360" />

Java方式:new RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,int pivotYType, float pivotYValue)

        Animation animation = new RotateAnimation(0f, -360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        animation.setDuration(1000);
        animation.setInterpolator(this, android.R.anim.accelerate_decelerate_interpolator);
        mImageView.startAnimation(animation);

translate畫面位置移動動畫

translate常用屬性:
android:fromXDelta,fromYDelta 起始時X,Y座標
android:toXDelta,toYDelta 動畫結束時X,Y的座標

xml方式

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

Java方式:new TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)

        Animation animation = new TranslateAnimation(0, 100, 0, 0);
        animation.setDuration(1000);
        animation.setInterpolator(this, android.R.anim.accelerate_decelerate_interpolator);
        mImageView.startAnimation(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:fillBefore="false"
        android:fromAlpha="1.0"
        android:toAlpha="0.0" />
    <translate
        android:duration="1000"
        android:fromXDelta="100"
        android:fromYDelta="0"
        android:interpolator="@android:anim/cycle_interpolator"
        android:toXDelta="0"
        android:toYDelta="0" />
</set>

xml方式載入方式通過AnimationUtils.loadAnimation再強轉AnimationSet取得animation物件

        AnimationSet animation = (AnimationSet) AnimationUtils.loadAnimation(this, R.anim.anim_set);
        mImageView.startAnimation(animation);

Java方式:

        AnimationSet animationSet = new AnimationSet(true);

        Animation translateAnimation = new TranslateAnimation(0, 100, 0, 0);
        translateAnimation.setDuration(1000);
        translateAnimation.setInterpolator(this, android.R.anim.accelerate_decelerate_interpolator);

        Animation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
        alphaAnimation.setDuration(1000);
        alphaAnimation.setFillBefore(false);

        animationSet.addAnimation(translateAnimation);
        animationSet.addAnimation(alphaAnimation);

        mImageView.startAnimation(animationSet);

動畫監聽器:

        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                //動畫開始時呼叫
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                //動畫結束時呼叫
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                //動畫重複時呼叫
            }
        });

幾種自帶的動畫插入器

用法:

animation.setInterpolator(new AnticipateInterpolator());

AccelerateInterpolator 加速,開始時慢中間加速
DecelerateInterpolator 減速,開始時快然後減速
AccelerateDecelerateInterolator 先加速後減速,開始結束時慢,中間加速
AnticipateInterpolator 反向,先向相反方向改變一段再加速播放
AnticipateOvershootInterpolator 反向加超越,先向相反方向改變,再加速播放,會超出目的值然後緩慢移動至目的值
BounceInterpolator 跳躍,快到目的值時值會跳躍,如目的值100,後面的值可能依次為85,77,70,80,90,100
CycleIinterpolator 迴圈,動畫迴圈一定次數,值的改變為一正弦函式:Math.sin(2* mCycles* Math.PI* input)
LinearInterpolator 線性,線性均勻改變
OvershootInterpolator超越,最後超出目的值然後緩慢改變到目的值

補間動畫缺點:
補間動畫還有一個最大的缺陷,就是它只是改變了View的繪製位置而已,並不會真正的改變View的屬性。具體來說,例如螢幕左上角有一個ImageView,使用補間動畫將其移動到左下角,此刻你去點選左下角的ImageView,它是絕對不會響應點選事件的,因此其作用區域依然還在原來的位置。只不過是補間動畫將其繪製在左下角而已。

上面就簡單的介紹了Android動畫基礎的補間動畫。我們接著來介紹另外一個動畫基礎——逐幀動畫。


逐幀動畫

幀——就是影像動畫中最小單位的單幅影像畫面,相當於電影膠片上的每一格鏡頭。 一幀就是一副靜止的畫面,連續的幀就形成動畫,所以對於經常看日番的朋友,對逐幀動畫一定很熟悉,當我們看到幀數很高的動畫就會不禁感嘆一句燃燒經費。
那麼從字面上理解,逐幀動畫Frame Animation就是一幀接著一幀的播放圖片。

Frame Animation動畫,也可以在xml檔案中進行配置,同樣在對於的資原始檔存放在res\anim的目錄下,配置檔案的問節點是

我們看一下常用的逐幀動畫屬性:
android:drawable 每一幀動畫的資源
android:duration 動畫持續時間
android:oneshot 是否只顯示一次,true為只顯示一次,false為重複顯示

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="@drawable/image_1"
        android:duration="200"/>
    <item
        android:drawable="@drawable/image_2"
        android:duration="200"/>
    <item
        android:drawable="@drawable/image_3"
        android:duration="200"/>
    ···
</animation-list>

xml方式載入方式,通過setImageResource()方法獲取資源配置檔案,通過getDrawable()方法取得元件的Drawable物件,通過AnimationDrawable的start()方法來啟動動畫。

        mImageView.setImageResource(R.anim.anim_frame);
        AnimationDrawable animationDrawable = (AnimationDrawable) mImageView.getDrawable();
        animationDrawable.setOneShot(false);
        animationDrawable.start();

純Java實現方式如下:

        AnimationDrawable animationDrawable = new AnimationDrawable();
        for (int i = 1; i <= N; i++) {
            int id = getResources().getIdentifier("image_" + i, "drawable", getPackageName());
            Drawable drawable = getResources().getDrawable(id, null);
            animationDrawable.addFrame(drawable, 200);
        }
        animationDrawable.setOneShot(false);
        mImageView.setImageDrawable(animationDrawable);
        animationDrawable.start();

從程式碼可以看出實現的方式都是一致的,我們看一下AnimationDrawable幾個常用的api:

void start() - 開始播放動畫
void stop() - 停止播放動畫
addFrame(Drawable frame, int duration) - 新增一幀,並設定該幀顯示的持續時間
void setOneShoe(boolean flag) - false為迴圈播放,true為僅播放一次
boolean isRunning() - 是否正在播放

好了,上述就是我們逐幀動畫的介紹,補間動畫和逐幀動畫都是Android動畫的基礎,下篇我們來研究一下另一重點——Android動畫之屬性動畫基礎用法

這裡寫圖片描述