Android Activity 轉場動畫

Android 設計 Activity 之間的轉場動畫大致有下列三類方法:
  1. overridePendingTransition
  2. ActivityOptionsCompat
  3. Theme Style


overridePendingTransition

這是 Android 典型的方法。
首先在 res/anim/ 目錄下建立 xml 檔來自訂動畫
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="100%p"
android:toXDelta="0"
android:duration="300"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"/>
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="0"
android:toXDelta="-100%p"
android:duration="300"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"/>
</set>

然後分別在 startActivity 下一行以及下一個 Activity 的 finish() 函式中加上 overridePendingTransition 即可呈現兩個 Activities 之間來回的轉場動畫。
Intent intent = new Intent();
intent.setClass(this, SecondActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.slide_left_enter, R.anim.slide_left_exit);
@Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.slide_right_enter, R.anim.slide_right_exit);
}

第一種方法的好處是直覺、自訂性高、且相容性高;缺點則是要分別在每個 startActivity 和 finish() 加上程式碼,不免覺得繁瑣。當程式碼量大的時候就不容易整理各個 Activity 之間的邏輯。

ActivityOptionsCompat

這是在 Android 5.0 後加入的新方法,也能向下相容舊版本。
用法是先宣告一個 ActivityOptionsCompat,並選擇它內建的方法去設定 xml,然後把它加入在 startActivity 的引數中即可。
// Set transition animation
ActivityOptionsCompat options = ActivityOptionsCompat.makeCustomAnimation(
context, R.anim.slide_left_enter, R.anim.slide_left_exit);
ActivityCompat.startActivity(activity, intent, options.toBundle());
至於返回的動畫則是在下一個 Activity 中加入 finishAfterTransition 這行來結束 Activity(相當於先執行動畫再 finish())。
@Override
public void onBackPressed() {
super.onBackPressed();
ActivityCompat.finishAfterTransition(this);
}
但卻發現直接這樣寫是沒有作用的!!
查了一下網路後,發現似乎是還要設定叫做「共享元素」的東西。這部份比較複雜,因此尚未研究清楚......
而 ActivityOptionsCompat 還有內建一些符合 Material Design 設計的動畫,如果只需要著重在進入轉場又懶得自訂 xml 的話則可以使用它們做出美觀的動畫。
ActivityOptionsCompat.makeClipRevealAnimation(View source, int startX, int startY, int width, int height)
ActivityOptionsCompat.makeScaleUpAnimation(View source, int startX, int startY, int startWidth, int startHeight)
ActivityOptionsCompat.makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY)
ActivityOptionsCompat.makeSceneTransitionAnimation(Activity activity, Pair...<View, String> sharedElements)
ActivityOptionsCompat.makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName)

Theme Style

第三種則是利用 styles.xml 設定自訂動畫,再指定該 Activity 的 Theme 來套用。
<style name="AppTheme.WithWindowAnim">
<item name="android:windowAnimationStyle">@style/ActivityAnim</item>
</style>
<style name="ActivityAnim">
<!-- Enter B Activity -->
<item name="android:activityOpenEnterAnimation">@anim/slide_left_enter</item> <!-- For B Activity -->
<item name="android:activityOpenExitAnimation">@anim/no_anim</item> <!-- For A Activity -->
<!-- Return B Activity -->
<item name="android:activityCloseEnterAnimation">@anim/slide_left_enter</item> <!-- For B Activity -->
<item name="android:activityCloseExitAnimation">@anim/no_anim</item> <!-- For C Activity -->
</style>
view raw styles.xml hosted with ❤ by GitHub
<activity
android:name=".SecondActivity"
android:theme="@style/AppTheme.WithWindowAnim" />
不過在使用這個方法時碰到了許多意料外的行為,所以對各種 key name 所代表的意義有疑惑。而且查了很多資料也看不懂敘述,只好自己嘗試整理出了下圖的規則:


這意思是說,假如我們對 B 設定 Theme,那麼動畫會在 A 進入 B,或者 C 返回 B 的情況下才有作用。因此各個 key name 的意義就如註解所示。
<style name="AppTheme.WithWindowAnim">
<item name="android:windowAnimationStyle">@style/ActivityAnim</item>
</style>
<style name="ActivityAnim">
<!-- Enter B Activity -->
<item name="android:activityOpenEnterAnimation">@anim/slide_left_enter</item> <!-- For B Activity -->
<item name="android:activityOpenExitAnimation">@anim/no_anim</item> <!-- For A Activity -->
<!-- Return B Activity -->
<item name="android:activityCloseEnterAnimation">@anim/slide_left_enter</item> <!-- For B Activity -->
<item name="android:activityCloseExitAnimation">@anim/no_anim</item> <!-- For C Activity -->
</style>
view raw styles.xml hosted with ❤ by GitHub

總結

整體來說,overridePendingTransition 可以在任何情境下使用,但需要逐一設定;
ActivityOptionsCompat 則是可以輕鬆使用內建的 Material Design 風格動畫,但正規的返回動畫實現方式還沒有弄清楚,可以使用 overridePendingTransition 來彌補;
設定 Theme 的方式則比較適合在該 Activity 無論在什麼情況下進入都要給予固定的動畫效果時使用。


留言

這個網誌中的熱門文章

Android 藍牙連接通訊實作心得

在 Android 上自訂 Zxing 掃描框樣式與大小位置