Android界面過渡動畫詳解

實現 activity 跳轉動畫的幾種方式

閱讀 13424

收藏 340

2016-07-09

原文鏈接:blog.csdn.net

轉載請標明出處:一片楓葉的專欄

上一篇文章中我們講解了在Activity啓動過程中獲取組件寬高的五種方式。在Activity的啓動過程中如果我們直接在生命週期方法中通過view.getWidth()或者是view.getHeight()方法獲取組件的寬度和高度其結果都是0,爲什麼會出現這個問題呢?

其實看過我以前寫過的Activity啓動流程  Activity佈局加載流程  Activity佈局繪製流程  的同學應該對Activity的啓動流程和其佈局加載繪製流程不陌生,Activity的啓動流程和Activity的佈局文件加載繪製流程,其實沒有相關的關係的,其實兩個異步的加載流程,這樣我們在Activity的onCreate或者是onResume方法中調用textView.getHeight()或者是textView.getWidth()方法的時候,Activity對應的組件並沒有執行完繪製流程,因此此時獲取到的組件的寬高都是默認的0,所以這時候通過getWidth()和getHeight()方法也就是無法獲取組件的寬和高了。

更多關於在Activity啓動過程中獲取組件寬高的知識,可參考我的:Activity啓動過程中獲取組件寬高的N種方式

文本中我們將講解activity切換動畫相關的知識點,這裏的切換動畫指的是是activity跳轉時的動畫效果。這裏總結了一下,有五種方式實現activity切換時實現動畫效果。下面我將依次介紹一下每種實現activity切換動畫效果的實現方式。

在介紹activity的切換動畫之前我們先來說明一下實現切換activity的兩種方式:

  • 調用startActivity方法啓動一個新的Activity並跳轉其頁面

  • 調用finish方法銷燬當前的Activity返回上一個Activity界面

當調用startActivity方法的時候啓動一個新的activity,這時候就涉及到了舊的Activity的退出動畫和新的Activity的顯示動畫;
當調用finish方法的時候,銷燬當前Acitivity,就涉及到了當前Activity的退出動畫和前一個Activity的顯示動畫;

所以我們的activity跳轉動畫是分爲兩個部分的:一個Activity的銷燬動畫與一個Activity的顯示動畫,明白了這一點之後我們開始看一下第一種實現Activity跳轉動畫的方式:通過overridePendingTransition方法實現Activity切換動畫。

(一)使用overridePendingTransition方法實現Activity跳轉動畫

overridePendingTransition方法是Activity中提供的Activity跳轉動畫方法,通過該方法可以實現Activity跳轉時的動畫效果。下面我們就將通過一個簡單的例子看一下如何通過overridePendingTransition方法實現Activity的切換動畫。

demo例子中我們實現了Activity a中有一個點擊按鈕,點擊按鈕實現跳轉Activity b的邏輯,具體代碼如下:

/**
 * 點擊按鈕實現跳轉邏輯
 */
button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 在調用了startActivity方法之後立即調用overridePendingTransition方法
                 */
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
                overridePendingTransition(R.anim.slide_in_left, R.anim.slide_in_left);
            }
        });

可以看到我們在調用了startActivity方法之後又執行了overridePendingTransition方法,而在overridePendingTransition方法中傳遞了兩個動畫布局文件,我們首先看一下這裏的動畫文件具體是怎麼實現的:



    

這裏的overridePendingTransition方法傳遞的是兩個動畫文件id,第一個參數是需要打開的Activity進入時的動畫,第二個參數是需要關閉的Activity離開時的動畫。這樣我們執行了這段代碼之後在跳轉Activity的時候就展示了動畫效果:
這裏寫圖片描述

動畫的效果是通過overridePendingTransition方法實現的,那麼下面我們來看一下overridePendingTransition方法的定義,我們在overridependingTransition方法在定義的時候有這樣的一段註釋說明:

/**
 * Call immediately after one of the flavors of {@link #startActivity(Intent)}
 * or {@link #finish} to specify an explicit transition animation to
 * perform next.
 */

/**
 * @param enterAnim A resource ID of the animation resource to use for
 * the incoming activity.  Use 0 for no animation.
 * @param exitAnim A resource ID of the animation resource to use for
 * the outgoing activity.  Use 0 for no animation.
 */

好吧,這段註釋,告訴通過註釋我們能夠知道:

  • overridePendingTransition方法需要在startAtivity方法或者是finish方法調用之後立即執行

  • 參數enterAnim表示的是從Activity a跳轉到Activity b,進入b時的動畫效果

  • 參數exitAnim表示的是從Activity a跳轉到Activity b,離開a時的動過效果

  • 若進入b或者是離開a時不需要動畫效果,則可以傳值爲0

好吧,本着批判的精神,我們來看一下是不是這樣的,首先看一下如果我們在startActivity方法調用之後不立即執行overridePendingTransition方法,會有動畫效果麼?

若我們將overridePendingTransition延時1s執行呢?

/**
 * 點擊按鈕實現跳轉邏輯
 */
button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
                overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_left);
                /**
                 * 延時1s執行overridePendingTransition方法
                 */
                button1.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        overridePendingTransition(R.anim.slide_in_top, R.anim.slide_in_top);
                    }
                }, 1000);

            }
        });

好吧,執行之後我們能夠發現跳轉動畫沒有了,所以overridePendingTransition只能在startActivity或者是finish方法之後執行。

還有一個問題,如果是在startActivity之後執行,只是在子線程中執行呢?activity的跳轉動畫能夠執行麼?

/**
 * 點擊按鈕實現跳轉邏輯
 */
button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
                overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_left);
                /**
                 * 在子線程中執行overridePendingTransition方法
                 */
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_left);
                    }
                }).start();

            }
        });

好吧,你沒有猜錯,activity的切換效果還是執行,也就是說overridePendingTransition方法也是可以在子線程中執行的,當然這並沒什麼卵用。

好吧,在介紹完了使用overridePendingTransition方法實現Activity切換動畫之後我們下面看一下使用style的方式定義實現Activity的切換動畫。

(二)使用style的方式定義Activity的切換動畫

(1)定義Application的style


(2)定義具體的AppTheme樣式

其中這裏的windowAnimationStyle就是我們定義Activity切換動畫的style。而@anim/slide_in_top就是我們定義的動畫文件,也就是說通過爲Appliation設置style,然後爲windowAnimationStyle設置動畫文件就可以全局的爲Activity的跳轉配置動畫效果。


    <
    



    
    

而在windowAnimationStyle中存在四種動畫:

activityOpenEnterAnimation 
activityOpenExitAnimation  
activityCloseEnterAnimation  
activityCloseExitAnimation  

(3)測試代碼,實現activity切換操作

/**
         * 點擊按鈕,實現Activity的跳轉操作
         * 通過定義style的方式實現activity的跳轉動畫
         */
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 普通的Intent跳轉Activity實現
                 */
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });

這時候我們我們執行diamante邏輯之後就能發現activity在切換的時候出現了動畫效果,說明我們設置的style起作用了。

(三)使用ActivityOptions切換動畫實現Activity跳轉動畫

上面我們講解的通過overridePendingTransition方法基本上可以滿足我們日常中對Activity跳轉動畫的需求了,但是MD風格出來之後,overridePendingTransition這種老舊、生硬的方式怎麼能適合我們的MD風格的App呢?好在google在新的sdk中給我們提供了另外一種Activity的過度動畫——ActivityOptions。並且提供了兼容包——ActivityOptionsCompat。ActivityOptionsCompat是一個靜態類,提供了相應的Activity跳轉動畫效果,通過其可以實現不少炫酷的動畫效果。

(1)在跳轉的Activity中設置contentFeature

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState)

        // 設置contentFeature,可使用切換動畫
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)
        Transition explode = TransitionInflater.from(this).inflateTransition(android.R.transition.explode)
        getWindow().setEnterTransition(explode)

        setContentView(R.layout.activity_three)
    }

這裏我們在Activity的setContentView之前調用了:

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)

方法,看過我的Activity佈局加載流程的同學應該知道,這裏的setFeature就是爲activity的窗口設置特性,不同的特性對應不同的佈局方式,比如可以設置無toolbar模式,有toolbar模式等等。而這裏設置的是需要過渡動畫,並且我們獲取了android中內置的explode動畫,並設值給了Activity的window窗口對象,這樣當Activity被啓動的時候就會執行explode所帶便的動畫效果了。

(2)在startActivity執行跳轉邏輯的時候調用startActivity的重寫方法,執行ActivityOptions.makeSceneTransitionAnimation方法

/**
         * 點擊按鈕,實現Activity的跳轉操作
         * 通過android5.0及以上代碼的方式實現activity的跳轉動畫
         */
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, ThreeActivity.class);
                startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this).toBundle());
            }
        });

這裏我們調用了startActivity的重載方法:

public void startActivity(Intent intent, @Nullable Bundle options)

並且我們傳入了ActivityOptions.makeSceneTransitionAnimation,該方法表示將Activity a平滑的切換到Activity b,其還有幾個重載方法可以指定相關的View,即以View爲焦點平滑的從Activity a切換到Activity b。

調用這段代碼之後我們activity跳轉的時候就展示出了動畫效果。
這裏寫圖片描述

(四)使用ActivityOptions之後內置的動畫效果通過style的方式

這種方式其實就是通過style的方式展示和使用ActivityOptions過度動畫,下面是實現通過定義style方式定義過度動畫的步驟:

(1)編寫過度動畫文件


 

首先我們需要在Application項目res目錄下新建一個transition目錄,然後創建資源文件,然後使用這些系統自帶的過渡動畫效果,這裏設置了過度時長爲300ms。

(2)定義style文件


        @color/colorPrimary
        @color/colorPrimaryDark
        @color/colorAccent

        @transition/activity_explode
        @transition/activity_explode
    

在Application的style文件中添加:

@transition/activity_explode
        @transition/activity_explode

並指定過渡動畫效果爲我們剛剛定義的過渡動畫文件。

(3)執行跳轉邏輯

/**
         * 點擊按鈕,實現Activity的跳轉操作
         * 通過android5.0及以上style的方式實現activity的跳轉動畫
         */
        button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 調用ActivityOptions.makeSceneTransitionAnimation實現過度動畫
                 */
                Intent intent = new Intent(MainActivity.this, FourActivity.class);
                startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this).toBundle());
            }
        });

這樣執行之後也可以展示出Activity跳轉過度動畫了,其和通過代碼方式實現的效果是類似的,而且這種動畫效果是全局的。

(五)使用ActivityOptions動畫共享組件的方式實現跳轉Activity動畫

這裏的共享組件動畫效果是指將前面一個Activity的某個子View與後面一個Activity的某個子View之間有過渡效果,即在這種過度效果下實現Activity的跳轉操作。那麼如何實現兩個組件View之間實現過渡效果呢?

(1)定義共享組件

在Activity a中的button按鈕點擊transitionName屬性:


 

在Activity b的佈局文件中爲組件定義transitionName屬性,這樣這兩個組件相當於有了過度對應關係,這裏需要注意的是這兩個組件的transitionName屬性的值必須是相同的。




    


(2)調用startActivity執行跳轉動畫

/**
         * 點擊按鈕,實現Activity的跳轉操作
         * 通過android5.0及以上共享組件的方式實現activity的跳轉動畫
         */
        button5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, FiveActivity.class);
                startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, button5, "shareNames").toBundle());
            }
        });

需要說明的是這裏調用的ActivityOptions.makeSceneTransitionAnimation方法,傳遞了三個參數,其中第一個參數爲context對象,第二個參數爲啓動Activity的共享組件,第三個參數爲啓動Activity的共享組件transitionName屬性值。

這樣經過調用之後我們就實現了從Activity a跳轉到Activity b的時候a中的組件到b中組件的過度效果。
這裏寫圖片描述

總結:

  • 本文主要講解了通過overridePendingTransition方式和ActivityOptions動畫API實現Activity的切換動畫效果;

  • overridePendingTransition方法從android2.0開始,基本上能夠覆蓋我們activity跳轉動畫的需求;

  • ActivityOptions API是在android5.0開始的,可以實現一些炫酷的動畫效果,更加符合MD風格;

  • ActivityOptions還可以實現兩個Activity組件之間的過度動畫;

  • 本項目例子已上傳待github中,歡迎star和follow,項目地址:實現activity跳轉動畫的五種方式


另外對github項目,開源項目解析感興趣的同學可以參考我的:
github項目解析(一)–>上傳android項目至github
github項目解析(二)–>將Android項目發佈至JCenter代碼庫
github項目解析(三)–>android內存泄露監測之leakcanary
github項目解析(四)–>動態更改TextView的字體大小
github項目解析(五)–>android日誌框架
github項目解析(六)–>自定義實現ButterKnife框架
github項目解析(七)–>防止按鈕重複點擊

 

轉載自:https://juejin.im/entry/5780b8481532bc005f2b81f3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章