使用動畫啟動活動

試試 Compose
Jetpack Compose 是 Android 推薦的 UI 工具包。瞭解如何在 Compose 中使用動畫。

在 Material Design 應用程式中,活動轉換會透過常見元素之間的動作和轉換,在不同狀態之間提供視覺連結。您可以指定進入和離開轉換的自訂動畫,以及活動之間轉換共用元素的動畫。

圖 1. 使用共用元素進行轉場。

  • 「進入」轉場效果可決定活動中的檢視區塊進入場景的方式。舉例來說,在explode進入轉場效果中,檢視區塊會從外部進入場景,並飛向畫面中央。
  • 「離開」轉場效果可決定活動中的檢視區塊離開場景的方式。舉例來說,在 explode 結束轉場效果中,檢視畫面會離開場景中心。
  • 「共用元素」轉場功能可決定兩個 Activity 之間切換移動時共用檢視畫面的方式。舉例來說,如果兩個活動在不同位置和大小有相同圖片,changeImageTransform共用元素轉換會在這些活動之間平滑地轉換和縮放圖片。

Android 支援下列進入和結束轉換:

  • explode:將檢視區塊移向或移出場景中心。
  • slide:將檢視區塊移入或移出場景的其中一個邊緣。
  • fade:變更檢視表的不透明度,藉此在場景中新增或移除檢視表。

系統支援將擴充 Visibility 類別的任何轉換做為進入或結束轉換。詳情請參閱 Transition 類別的 API 參考資料。

Android 也支援下列共用元素轉場效果:

  • changeBounds:為目標檢視區塊的版面配置邊界變化製作動畫。
  • changeClipBounds:為目標檢視區塊的剪輯邊界變化製作動畫。
  • changeTransform:為目標檢視區塊的縮放和旋轉變化製作動畫。
  • changeImageTransform:為目標圖片的大小和比例變化製作動畫。

在應用程式中啟用活動轉換時,系統會在進入和結束活動之間啟動預設的淡入淡出轉換效果。

圖 2. 使用一個共用元素進行場景轉場。

如需使用共用元素在活動之間加入動畫效果的程式碼範例,請參閱「ActivitySceneTransitionBasic」。

檢查系統版本

活動轉換 API 適用於 Android 5.0 (API 21) 以上版本。為確保與舊版 Android 相容,請在執行任何這些功能的 API 前,先在執行階段檢查系統 version

Kotlin

// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Apply activity transition
} else {
    // Swap without transition
}

Java

// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Apply activity transition
} else {
    // Swap without transition
}

指定自訂轉場效果

首先,定義從 Material 主題繼承的樣式時,請使用 android:windowActivityTransitions 屬性啟用視窗內容轉場效果。您也可以在樣式定義中指定進入、離開和共用元素轉場效果:

<style name="BaseAppTheme" parent="android:Theme.Material">
  <!-- enable window content transitions -->
  <item name="android:windowActivityTransitions">true</item>

  <!-- specify enter and exit transitions -->
  <item name="android:windowEnterTransition">@transition/explode</item>
  <item name="android:windowExitTransition">@transition/explode</item>

  <!-- specify shared element transitions -->
  <item name="android:windowSharedElementEnterTransition">
    @transition/change_image_transform</item>
  <item name="android:windowSharedElementExitTransition">
    @transition/change_image_transform</item>
</style>

本例中的 change_image_transform 轉場定義如下:

<!-- res/transition/change_image_transform.xml -->
<!-- (see also Shared Transitions below) -->
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
  <changeImageTransform/>
</transitionSet>

changeImageTransform 元素對應於 ChangeImageTransform 類別。詳情請參閱 Transition 的 API 參考資料。

如要在程式碼中啟用視窗內容轉場效果,請呼叫 Window.requestFeature() 函式:

Kotlin

// Inside your activity (if you did not enable transitions in your theme)
with(window) {
    requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)

    // Set an exit transition
    exitTransition = Explode()
}

Java

// Inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);

// Set an exit transition
getWindow().setExitTransition(new Explode());

如要在程式碼中指定轉場效果,請使用 Transition 物件呼叫下列函式:

setExitTransition()setSharedElementExitTransition() 函式會定義呼叫活動的結束轉場效果。setEnterTransition()setSharedElementEnterTransition() 函式會定義所呼叫活動的進入轉場效果。

如要充分發揮轉場效果,您必須在呼叫和被呼叫的活動中,啟用視窗內容轉場效果。否則,通話活動會啟動結束轉場效果,但您會看到視窗轉場效果,例如縮放或淡出。

如要盡快啟動進入轉場效果,請在所呼叫的活動中使用 Window.setAllowEnterTransitionOverlap() 函式。這樣一來,您就能有更戲劇化的進入轉場效果。

使用轉場效果啟動活動

如果您啟用轉場效果並為活動設定結束轉場效果,當您啟動其他活動時,系統會啟動轉場效果,如下所示:

Kotlin

startActivity(intent,
              ActivityOptions.makeSceneTransitionAnimation(this).toBundle())

Java

startActivity(intent,
              ActivityOptions.makeSceneTransitionAnimation(this).toBundle());

如果您為第二項活動設定進入轉場效果,該轉場效果也會在活動啟動時啟用。如要在啟動其他活動時停用轉場效果,請提供 null 選項套件。

使用共用元素啟動活動

如要在兩個含有共用元素的活動之間製作畫面轉場動畫,請按照下列步驟操作:

  1. 在主題中啟用視窗內容轉場效果。
  2. 在樣式中指定共用元素轉換。
  3. 將轉場效果定義為 XML 資源。
  4. 使用 android:transitionName 屬性,為兩個版面配置中的共用元素指派通用名稱。
  5. 使用 ActivityOptions.makeSceneTransitionAnimation() 函式。

Kotlin

// Get the element that receives the click event
val imgContainerView = findViewById<View>(R.id.img_container)

// Get the common element for the transition in this activity
val androidRobotView = findViewById<View>(R.id.image_small)

// Define a click listener
imgContainerView.setOnClickListener( {
    val intent = Intent(this, Activity2::class.java)
    // Create the transition animation - the images in the layouts
    // of both activities are defined with android:transitionName="robot"
    val options = ActivityOptions
            .makeSceneTransitionAnimation(this, androidRobotView, "robot")
    // Start the new activity
    startActivity(intent, options.toBundle())
})

Java

// Get the element that receives the click event
final View imgContainerView = findViewById(R.id.img_container);

// Get the common element for the transition in this activity
final View androidRobotView = findViewById(R.id.image_small);

// Define a click listener
imgContainerView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(this, Activity2.class);
        // Create the transition animation - the images in the layouts
        // of both activities are defined with android:transitionName="robot"
        ActivityOptions options = ActivityOptions
            .makeSceneTransitionAnimation(this, androidRobotView, "robot");
        // Start the new activity
        startActivity(intent, options.toBundle());
    }
});

如要使用您在程式碼中產生的共用動態檢視區塊,請使用 View.setTransitionName() 函式,在兩個活動中指定通用元素名稱。

如要在第二個 Activity 結束時反向執行場景轉場動畫,請呼叫 Activity.finishAfterTransition() 函式,而非 Activity.finish()

使用多個共用元素啟動活動

如要在兩個 Activity 之間製作轉場動畫,且這兩個 Activity 有多個共用元素,請使用 android:transitionName 屬性在兩個版面配置中定義共用元素,或在兩個 Activity 中使用 View.setTransitionName() 函式,然後建立 ActivityOptions 物件,如下所示:

Kotlin

// Rename the Pair class from the Android framework to avoid a name clash
import android.util.Pair as UtilPair
...
val options = ActivityOptions.makeSceneTransitionAnimation(this,
        UtilPair.create(view1, "agreedName1"),
        UtilPair.create(view2, "agreedName2"))

Java

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
        Pair.create(view1, "agreedName1"),
        Pair.create(view2, "agreedName2"));