Android學(xué)習(xí)筆記(七)| Android動畫(上)—— View動畫

參考書籍:《Android開發(fā)藝術(shù)探索》 任玉剛
如有錯漏,請批評指出!

最近學(xué)習(xí)自定義View過程中,頻繁使用到動畫效果的控制,由于對這部分了解尚少,因此在這里系統(tǒng)的學(xué)習(xí)一下。

Android 中動畫可以分為三種:View動畫、幀動畫和屬性動畫。View動畫通過對場景中的對象進(jìn)行平移、旋轉(zhuǎn)、縮放、改變透明度等變換,從而產(chǎn)生動畫效果,它是一種漸進(jìn)式動畫;幀動畫通過順序播放一系列圖像從而產(chǎn)生動畫效果,但圖片過多過大時可能導(dǎo)致OOM;屬性動畫通過動態(tài)改變對象的屬性從而達(dá)到動畫效果,屬性動畫為API 11 新特性,在低版本中可以通過兼容庫來使用它。下面我們先來看View動畫。

View 動畫的種類

View動畫的作用對象是View,它支持四種動畫效果,分別是平移動畫、旋轉(zhuǎn)動畫、縮放動畫和透明度動畫,它們分別對應(yīng)著 Animation 的四個子類:TranslateAnimation、RotateAnimation、ScaleAnimation、AlphaAnimation,如下表:

名稱 xml標(biāo)簽 子類 效果
平移動畫 <translate> TranslateAnimation 移動View
縮放動畫 <scale> ScaleAnimation 縮小或放大View
旋轉(zhuǎn)動畫 <rotate> RotateAnimation 旋轉(zhuǎn)View
透明度動畫 <alpha> AlphaAnimation 改變View的透明度

這四種動畫既可以通過xml來定義,也可以通過代碼來動態(tài)創(chuàng)建,不過通過xml定義可讀性更好。下面來看一下如何通過xml定義。
首先在res目錄下新建一個 anim 目錄,在這個目錄下新建一個 Animation resource file ,即:res/anim/anim_filename.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

</set>
<set/> 標(biāo)簽

這是創(chuàng)建的文件的結(jié)構(gòu),它默認(rèn)有一個 <set/> 標(biāo)簽,表示動畫集合,因為一個動畫效果可以由上面的四種動畫組合起來,下面我們來看一下它的一些屬性:

  • 基本屬性:
屬性 作用 屬性值
duration 設(shè)置動畫持續(xù)時間(ms) 例如:5000 即:5s
fillAfter 設(shè)置動畫結(jié)束后View是否恢復(fù)初始狀態(tài) true 或 false
fillBefore 設(shè)置動畫結(jié)束后View變換效果是否保留(放大、縮小、透明度) true 或 false
repeatMode 設(shè)置動畫重復(fù)模式 reverse —— 倒序回放 restart —— 重置開始
repeatCount 設(shè)置動畫重復(fù)次數(shù)(在具體動畫中指定才會生效) 例如:10 即重復(fù)10次(特別:-1表示無限循環(huán))
startOffset 設(shè)置動畫延遲開始時間(ms)(即start之后等待一段時間開始) 例如:1000 即延遲1s開始
  • 進(jìn)階屬性:
屬性 作用 屬性值
interpolator 設(shè)置動畫的插值器,使基本動畫效果以勻速、加速、減速、拋物線速率等速率變化 默認(rèn)為 @android:/anim/accelerate_decelerate_interpolator 即加速減速插值器
shareInterpolator 設(shè)置集合中動畫是否和集合共享一個插值器 true 或 false(設(shè)置為 false 則需要單獨為集合中動畫設(shè)置插值器)
<translate/> 標(biāo)簽
  • 基本屬性(坐標(biāo)均相對于View自身而言,View左上角即(0, 0))
屬性 描述
fromXDelta 起始 x 坐標(biāo)
fromYDelta 起始 y 坐標(biāo)
toXDelta 結(jié)束 x 坐標(biāo)
toYDelta 結(jié)束 y 坐標(biāo)
  • 示例
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fillAfter="true"
    android:fillBefore="true"
    android:repeatMode="reverse"
    android:startOffset="100">

    <translate
        android:fromXDelta="0.0"
        android:fromYDelta="0.0"
        android:toXDelta="200.0"
        android:toYDelta="100.0"
        android:repeatCount="-1"/>
</set>
<rotate/> 標(biāo)簽
  • 基本屬性(坐標(biāo)均相對于View自身而言,View左上角即(0,0))
屬性 描述
fromDegrees 旋轉(zhuǎn)初始角度
toDegrees 旋轉(zhuǎn)結(jié)束角度
pivotX 旋轉(zhuǎn)軸點 x 坐標(biāo)(默認(rèn)0)
pivotY 旋轉(zhuǎn)軸點 y 坐標(biāo)(默認(rèn)0)

注意:旋轉(zhuǎn)軸點默認(rèn)為View左上角,即(0, 0)

  • 示例
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fillAfter="true"
    android:fillBefore="true"
    android:repeatMode="reverse"
    android:startOffset="100" >

    <rotate
        android:fromDegrees="0"
        android:toDegrees="-180"
        android:pivotX="100"
        android:pivotY="-50"
        android:repeatCount="-1"/>
</set>
<scale/> 標(biāo)簽
  • 基本屬性(坐標(biāo)均相對于View自身而言,View左上角即(0,0))
屬性 描述
fromXScale 初始X軸縮放比例(1.0 表示初始大小)
fromYScale 初始Y軸縮放比例(1.0 表示初始大?。?/td>
toXScale 結(jié)束X軸縮放比例(相對于View自身大?。?/td>
toYScale 結(jié)束Y軸縮放比例(相對于View自身大?。?/td>
pivotX 縮放軸點 x 坐標(biāo)(默認(rèn)0)
pivotY 縮放軸點 y 坐標(biāo)(默認(rèn)0)

注意:旋轉(zhuǎn)軸點默認(rèn)為View左上角,即(0, 0)

  • 示例
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fillAfter="true"
    android:fillBefore="true"
    android:repeatMode="reverse"
    android:startOffset="100" >

    <scale
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:toXScale="2.0"
        android:toYScale="2.0"
        android:pivotX="0"
        android:pivotY="0"
        android:repeatCount="-1"/>
</set>
<rotate/> 標(biāo)簽
  • 基本屬性(坐標(biāo)均相對于View自身而言,View左上角即(0,0))
屬性 描述
fromAlpha 起始透明度(1.0表示正常狀態(tài))
toAlpha 結(jié)束透明度(0.0~1.0之間)

注意:旋轉(zhuǎn)軸點默認(rèn)為View左上角,即(0, 0)

  • 示例
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fillAfter="true"
    android:fillBefore="true"
    android:repeatMode="reverse"
    android:startOffset="100" >

    <alpha
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
        android:repeatCount="-1"/>
</set>
xml定義動畫的調(diào)用方式:

調(diào)用 AnimationUtils 類的 loadAnimation(Context context, @AnimRes int id) 方法可以得到一個 Animation 對象,第二個參數(shù)就是定義動畫的 Amimation 資源文件,然后調(diào)用控件的 startAnimation(Animation animation) 方法將 Animation 對象傳入即可。下面看代碼:

public class ViewAnimActivity extends AppCompatActivity {

    @BindView(R.id.tv_translate) TextView tvTranslate;
    @BindView(R.id.tv_rotate) TextView tvRotate;
    @BindView(R.id.tv_scale) TextView tvScale;
    @BindView(R.id.tv_alpha) TextView tvAlpha;

    private Animation translateAnimation;
    private Animation rotateAnimation;
    private Animation scaleAnimation;
    private Animation alphaAnimation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_anim);
        ButterKnife.bind(this);

        translateAnimation = AnimationUtils.loadAnimation(this, R.anim.view_anim01);
        rotateAnimation = AnimationUtils.loadAnimation(this, R.anim.view_anim02);
        scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.view_anim03);
        alphaAnimation = AnimationUtils.loadAnimation(this, R.anim.view_anim04);
    }

    @OnClick(R.id.but_start)
    public void onClock() {
        tvTranslate.startAnimation(translateAnimation);
        tvRotate.startAnimation(rotateAnimation);
        tvScale.setAnimation(scaleAnimation);
        tvAlpha.setAnimation(alphaAnimation);
    }
}

接下來看看上面這四個示例的效果:
代碼動態(tài)創(chuàng)建View動畫

當(dāng)然,上面的動畫效果也可以用Java代碼實現(xiàn),以第一個平移動畫為例:

    TranslateAnimation mTranslateAnimation = new TranslateAnimation(0.0f, 200.0f, 0.0f, 100.0f);
    mTranslateAnimation.setDuration(1000);
    mTranslateAnimation.setRepeatMode(Animation.REVERSE);
    mTranslateAnimation.setRepeatCount(Animation.INFINITE);//即 -1
    mTranslateAnimation.setFillAfter(true);
    mTranslateAnimation.setFillBefore(true);
    tvTranslate.startAnimation(mTranslateAnimation);

這段代碼實現(xiàn)的效果與前面使用xml定義的平移動畫的效果是一模一樣的,理解起來也很簡單。另外,通過 Animation 的 setAnimationListener() 方法,可以給 View 動畫添加過程監(jiān)聽,接口源碼如下:

    public static interface AnimationListener {
        /**
         * <p>Notifies the start of the animation.</p>
         *
         * @param animation The started animation.
         */
        void onAnimationStart(Animation animation);

        /**
         * <p>Notifies the end of the animation. This callback is not invoked
         * for animations with repeat count set to INFINITE.</p>
         *
         * @param animation The animation which reached its end.
         */
        void onAnimationEnd(Animation animation);

        /**
         * <p>Notifies the repetition of the animation.</p>
         *
         * @param animation The animation which was repeated.
         */
        void onAnimationRepeat(Animation animation);
    }

這三個接口分別在動畫開始、結(jié)束及重復(fù)的時候回調(diào)。

View動畫的特殊使用場景

前面是關(guān)于View動畫的四種基本形式,除此之外,View動畫還可以在一些特殊情景下使用,比如在 ViewGroup 中可以控制子元素的顯示效果,在 Activity 中可以實現(xiàn)不同Activity之間的切換效果。

LayoutAnimation 的使用

LayoutAnimation 作用于ViewGroup,為ViewGroup指定一個動畫,這樣當(dāng)它的子元素顯示時都會具有這種動畫效果,這種效果通常被用在ListView上,下面來看一下具體用法:

  • LayoutAnimation 基本屬性
屬性 描述
delay 子元素開始動畫的時間延遲,例如子元素的動畫 duration 指定為 1000ms,delay指定為0.1 表示每個子元素都會在前一個子元素顯示之后延遲 100ms 開始顯示動畫
animationOrder 子元素動畫的順序,normal——順序顯示、reverse——倒序顯示、random——隨機顯示
animation 指定子元素顯示動畫
  • 示例
    1.定義子 item 顯示動畫:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:shareInterpolator="true"
    android:interpolator="@android:anim/accelerate_interpolator">

    <alpha android:fromAlpha="0.0"
        android:toAlpha="1.0"/>

    <translate
        android:fromXDelta="500.0"
        android:toXDelta="0.0"/>
</set>
  1. 定義LayoutAnimation(xml定義和代碼動態(tài)定義都可以)
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:delay="0.5"
    android:animationOrder="normal"
    android:animation="@anim/layout_anim_item"/>
  1. 給ListView 指定 LayoutAnimation
<ListView
    android:id="@+id/list_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layoutAnimation="@anim/layout_anim01"/>
  1. ListView 的使用照常(簡單起見,這里使用系統(tǒng)內(nèi)置的item布局,給出關(guān)鍵代碼)
    ArrayAdapter<String> mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, listData);
    mListView.setAdapter(mAdapter);

最后來看一下實現(xiàn)效果:
  • 代碼創(chuàng)建LayoutAnimation:通過 LayoutAnimationController 來實現(xiàn)
    Animation animation = AnimationUtils.loadAnimation(this, R.anim.layout_anim_item);
    LayoutAnimationController controller = new LayoutAnimationController(animation);
    controller.setDelay(0.5f);
    controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
    mListView.setLayoutAnimation(controller);

    ArrayAdapter<String> mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, listData);
    mListView.setAdapter(mAdapter);
Activity的切換效果

Activity有默認(rèn)的切換效果,不過這個效果我們是可以自定義的,主要用到overridePendingTransition(int enterAnim, int exitAnim) 這個方法,這個方法必須在 startActivity(Intent intent) 或者 finish() 方法之后才會生效。這個方法接收兩個參數(shù):

  • enterAnim—— Activity被打開時,所需要的動畫資源
  • exitAnim—— Activity被暫停時, 所需要的動畫資源
    Intent intent = new Intent(this, ViewAnimActivity.class);
    startActivity(intent);
    overridePendingTransition(R.anim.activity_enter_anim, R.anim.activity_exit_anim);

具體的動畫效果自己定義即可。


上一篇:Android學(xué)習(xí)筆記(六)| View的工作原理(下)
下一篇:Android學(xué)習(xí)筆記(八)| Android動畫(中)—— 幀動畫

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容