實現Activity跳轉動畫的五種方式
文字中我們將講解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);
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
可以看到我們在呼叫了startActivity方法之後又執行了overridePendingTransition方法,而在overridePendingTransition方法中傳遞了兩個動畫布局檔案,我們首先看一下這裡的動畫檔案具體是怎麼實現的:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:shareInterpolator="false"
Android:zAdjustment="top">
<translate
Android:duration="200"
Android:fromXDelta="-100.0%p"
Android:toXDelta="0.0" />
</set>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
這裡的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.
*/
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
好吧,這段註釋,告訴通過註釋我們能夠知道:
-
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);
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
好吧,執行之後我們能夠發現跳轉動畫沒有了,所以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();
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
好吧,你沒有猜錯,activity的切換效果還是執行,也就是說overridePendingTransition方法也是可以在子執行緒中執行的,當然這並沒什麼卵用。
好吧,在介紹完了使用overridePendingTransition方法實現Activity切換動畫之後我們下面看一下使用style的方式定義實現Activity的切換動畫。
(二)使用style的方式定義Activity的切換動畫
(1)定義Application的style
<!-- 系統Application定義 -->
<application
Android:allowBackup="true"
Android:icon="@mipmap/ic_launcher"
Android:label="@string/app_name"
Android:supportsRtl="true"
Android:theme="@style/AppTheme">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
(2)定義具體的AppTheme樣式
其中這裡的windowAnimationStyle就是我們定義Activity切換動畫的style。而@anim/slide_in_top就是我們定義的動畫檔案,也就是說通過為Appliation設定style,然後為windowAnimationStyle設定動畫檔案就可以全域性的為Activity的跳轉配置動畫效果。
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="Android:windowAnimationStyle">@style/activityAnim</item>
</style>
<!-- 使用style方式定義activity切換動畫 -->
<style name="activityAnim">
<item name="Android:activityOpenEnterAnimation">@anim/slide_in_top</item>
<item name="Android:activityOpenExitAnimation">@anim/slide_in_top</item>
</style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
而在windowAnimationStyle中存在四種動畫:
activityOpenEnterAnimation // 用於設定開啟新的Activity並進入新的Activity展示的動畫
activityOpenExitAnimation // 用於設定開啟新的Activity並銷燬之前的Activity展示的動畫
activityCloseEnterAnimation // 用於設定關閉當前Activity進入上一個Activity展示的動畫
activityCloseExitAnimation // 用於設定關閉當前Activity時展示的動畫
- 1
- 2
- 3
- 4
(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);
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
這時候我們我們執行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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
這裡我們在Activity的setContentView之前呼叫了:
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
- 1
方法,看過我的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());
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
這裡我們呼叫了startActivity的過載方法:
public void startActivity(Intent intent, @Nullable Bundle options)
- 1
並且我們傳入了ActivityOptions.makeSceneTransitionAnimation,該方法表示將Activity a平滑的切換到Activity b,其還有幾個過載方法可以指定相關的View,即以View為焦點平滑的從Activity a切換到Activity b。
呼叫這段程式碼之後我們activity跳轉的時候就展示出了動畫效果。
(四)使用ActivityOptions之後內建的動畫效果通過style的方式
這種方式其實就是通過style的方式展示和使用ActivityOptions過度動畫,下面是實現通過定義style方式定義過度動畫的步驟:
(1)編寫過度動畫檔案
<explode xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:duration="300" />
- 1
- 2
首先我們需要在Application專案res目錄下新建一個transition目錄,然後建立資原始檔,然後使用這些系統自帶的過渡動畫效果,這裡設定了過度時長為300ms。
(2)定義style檔案
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="Android:windowEnterTransition">@transition/activity_explode</item>
<item name="Android:windowExitTransition">@transition/activity_explode</item>
</style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
在Application的style檔案中新增:
<item name="Android:windowEnterTransition">@transition/activity_explode</item>
<item name="Android:windowExitTransition">@transition/activity_explode</item>
- 1
- 2
並指定過渡動畫效果為我們剛剛定義的過渡動畫檔案。
(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());
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
這樣執行之後也可以展示出Activity跳轉過度動畫了,其和通過程式碼方式實現的效果是類似的,而且這種動畫效果是全域性的。
(五)使用ActivityOptions動畫共享元件的方式實現跳轉Activity動畫
這裡的共享元件動畫效果是指將前面一個Activity的某個子View與後面一個Activity的某個子View之間有過渡效果,即在這種過度效果下實現Activity的跳轉操作。那麼如何實現兩個元件View之間實現過渡效果呢?
(1)定義共享元件
在Activity a中的button按鈕點選transitionName屬性:
<Button
Android:id="@+id/button5"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_below="@+id/button4"
Android:layout_marginTop="10dp"
Android:layout_marginRight="10dp"
Android:layout_marginLeft="10dp"
Android:text="元件過度動畫"
Android:background="@color/colorPrimary"
Android:transitionName="shareNames"
/>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
在Activity b的佈局檔案中為元件定義transitionName屬性,這樣這兩個元件相當於有了過度對應關係,這裡需要注意的是這兩個元件的transitionName屬性的值必須是相同的。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/activity_second"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:gravity="center_horizontal"
Android:orientation="vertical"
Android:transitionName="shareNames"
>
<TextView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@color/colorAccent"
Android:layout_marginTop="10dp"
Android:layout_marginBottom="10dp"
/>
</LinearLayout>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
(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());
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
需要說明的是這裡呼叫的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跳轉動畫的五種方式