Kotlin 03.2 版的 Android 進階功能:透過 MotionLayout 建立動畫

1. 事前準備

這個程式碼研究室是 Android Kotlin 進階功能課程的一部分。如果你依序完成程式碼研究室,就能充分發揮本課程的價值,但這不是強制要求。所有課程程式碼研究室都會列在「Android Kotlin 的進階程式碼研究室到達網頁」中。

MotionLayout 是一個程式庫,可讓您在 Android 應用程式中加入豐富的動態功能。它是以 ConstraintLayout, 為基礎,可用來為可透過 ConstraintLayout 建構的內容建立動畫。

您可以使用 MotionLayout,同時為多個檢視畫面的位置、大小、顯示設定、Alpha 通道、顏色、高度、旋轉和其他屬性設定動畫效果。使用宣告式 XML 時,您可以建立包含多個檢視畫面的協調動畫,而難以在程式碼中實現。

動畫是提升應用程式體驗的絕佳方式。動畫的用途如下:

  • 顯示變更:在狀態之間建立動畫效果,可讓使用者自然追蹤 UI 的變化。
  • 吸引註意力:運用動畫將注意力吸引到重要的 UI 元素。
  • 打造美觀的設計:在設計中加入有效的動態效果,可讓應用程式看起來更精美。

必要條件

本程式碼研究室是為具備部分 Android 開發經驗的開發人員而設計。嘗試完成本程式碼研究室之前,請先:

  • 瞭解如何使用活動和基本版面配置建立應用程式,以及使用 Android Studio 在裝置或模擬器上執行應用程式。熟悉 ConstraintLayout。詳閱限製版面配置程式碼研究室,進一步瞭解 ConstraintLayout

執行步驟

  • 使用 ConstraintSetsMotionLayout 定義動畫
  • 根據拖曳事件製作動畫
  • 使用 KeyPosition 變更動畫
  • 使用 KeyAttribute 變更屬性
  • 透過程式碼執行動畫
  • 使用 MotionLayout 為可收合標頭建立動畫

軟硬體需求

  • Android Studio 4.0 (MotionLayout 編輯器僅適用於這個版本的 Android Studio)。

2. 踏出第一步

如要下載範例應用程式,請執行下列任一操作:

... 或是使用以下指令從指令列複製 GitHub 存放區:

$ git clone https://github.com/googlecodelabs/motionlayout.git

3. 使用 MotionLayout 建立動畫

首先,您會建立動畫,以便在使用者按下廣告後,將檢視畫面從螢幕頂端移至底部。

如要透過範例程式碼建立動畫,您需要下列主要部分:

  • MotionLayout,ConstraintLayout 的子類別。您可以在 MotionLayout 標記中指定要動畫的所有檢視畫面。
  • MotionScene,,這是描述 MotionLayout. 動畫的 XML 檔案
  • Transition,MotionScene 的一部分,用於指定動畫持續時間、觸發條件,以及移動檢視畫面的方式。
  • ConstraintSet 會同時指定轉場效果的 startend 限制。

讓我們從 MotionLayout 開始,逐一瞭解這些轉換。

步驟 1:探索現有程式碼

MotionLayoutConstraintLayout 的子類別,因此可在新增動畫時支援所有相同的功能。如要使用 MotionLayout,請新增 MotionLayout 檢視畫面,而您應該在其中使用 ConstraintLayout.

  1. res/layout 中開啟 activity_step1.xml.,這裡有一個 ConstraintLayout 含有一個星號的 ImageView,並在其中套用了色調。

activity_step1.xml

<!-- initial code -->
<androidx.constraintlayout.widget.ConstraintLayout
       ...
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       >

   <ImageView
           android:id="@+id/red_star"
           ...
   />

</androidx.constraintlayout.motion.widget.MotionLayout>

ConstraintLayout 沒有任何限制,因此如果您現在執行應用程式,會看到星號螢幕不受限制,因此星號圖示會放在不明位置。Android Studio 會向您發出沒有限制條件的警告。

步驟 2:轉換為動態版面配置

如要使用 MotionLayout, 製作動畫,您必須將 ConstraintLayout 轉換為 MotionLayout

如要在版面配置中使用動態場景,必須將其指向該動態場景。

  1. 方法是開啟設計介面。在 Android Studio 4.0 中,查看版面配置 XML 檔案時,使用右上方的分割或設計圖示,開啟設計介面。

a2beea710c2decb7.png

  1. 開啟設計介面後,在預覽畫面上按一下滑鼠右鍵,然後選取「Convert to MotionLayout」

4fa936a98a8393b9.png

這會將 ConstraintLayout 標記替換為 MotionLayout 標記,並將 motion:layoutDescription 新增至指向 @xml/activity_step1_scene.MotionLayout 標記

activity_step1**.xml**

<!-- explore motion:layoutDescription="@xml/activity_step1_scene" -->
<androidx.constraintlayout.motion.widget.MotionLayout
       ...
       motion:layoutDescription="@xml/activity_step1_scene">

動態場景是描述 MotionLayout 中動畫的單一 XML 檔案。

轉換為 MotionLayout 後,設計介面會顯示 Motion Editor

66d0e80d5ab4daf8.png

Motion Editor 中有三個新的 UI 元素:

  1. Overview (總覽) - 這項功能選取模式,可讓你選取動畫的不同部分。在這張圖片中,已選取 start ConstraintSet。您也可以按一下 startend 之間的箭頭,選取轉場效果。
  2. 區段:總覽下方是版面視窗,會根據目前選取的總覽項目變更。在這張圖片中,選取視窗會顯示 start ConstraintSet 資訊。
  3. 屬性 - 屬性面板會顯示總覽或選取視窗中目前所選項目的屬性。這張圖片顯示 start ConstraintSet 的屬性。

步驟 3:定義開始和結束限制條件

所有動畫都能以開始和結束來定義。開始說明畫面在動畫開始前的外觀,結尾則說明畫面在動畫結束後的外觀。MotionLayout 負責確保開始和結束狀態 (指定時間) 之間的動畫效果。

MotionScene 會使用 ConstraintSet 標記定義開始和結束狀態。ConstraintSet 看起來是這樣的情況,也就是可套用至檢視區塊的一組限制條件。包括寬度、高度和 ConstraintLayout 限制。以及 alpha 等部分屬性。其中不含檢視畫面,只是這些檢視畫面的限制。

ConstraintSet 中指定的任何限制條件都會覆寫版面配置檔案中指定的限制。如果您在版面配置和 MotionScene 中定義限制條件,系統只會套用 MotionScene 中的限制條件。

在這個步驟中,您會限制星星檢視從螢幕頂端開始,到畫面底部結束。

如要完成這個步驟,您可以使用 Motion Editor,或是直接編輯 activity_step1_scene.xml 的文字。

  1. 在總覽面板中選取 start ConstraintSet

6e57661ed358b860.png

  1. 在「selection」面板中,選取 red_star。目前僅顯示 layout 的來源,這表示該項目在此 ConstraintSet 中不會受到限制。使用右上方的鉛筆圖示來「建立限制」

f9564c574b86ea8.gif

  1. 確認在總覽面板中選取 start ConstraintSet 時,red_star 會顯示 start 的來源。
  2. 在「Attributes」面板中,選取 start ConstraintSet 中的「red_star」,然後在頂端新增「Constraint」,接著點選藍色的 按鈕。

2fce076cd7b04bd.png

  1. 開啟 xml/activity_step1_scene.xml 即可查看 Motion Editor 為這項限制產生的程式碼。

activity_step1_scene.xml

<!-- Constraints to apply at the start of the animation -->
<ConstraintSet android:id="@+id/start">
   <Constraint
           android:id="@+id/red_star"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           motion:layout_constraintStart_toStartOf="parent"
           motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>

ConstraintSetid@id/start,並指定套用至 MotionLayout 中所有檢視畫面的所有限制條件。由於這個 MotionLayout 只有一項資料檢視,因此只需要一個 Constraint

ConstraintSet 中的 Constraint 會指定限制檢視畫面的 ID (在 activity_step1.xml 中定義)。@id/red_star請務必注意,Constraint 標記只會指定限制和版面配置資訊。Constraint 標記不知道已套用至 ImageView

這項限制可指定將 red_star 檢視區塊限制為其父項頂端開頭所需的高度、寬度及其他兩項限制。

  1. 在總覽面板中選取 end ConstraintSet。

346e1248639b6f1e.png

  1. 按照上述步驟在 end ConstraintSet 中新增 red_starConstraint
  2. 如要使用 Motion Editor 完成這個步驟,請點按藍色的 + 按鈕,在 bottomend 中加入限制。

fd33c779ff83c80a.png

  1. XML 中的程式碼如下所示:

activitiy_step1_scene.xml

<!-- Constraints to apply at the end of the animation -->
<ConstraintSet android:id="@+id/end">
   <Constraint
           android:id="@+id/red_star"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           motion:layout_constraintEnd_toEndOf="parent"
           motion:layout_constraintBottom_toBottomOf="parent" />
</ConstraintSet>

@id/start 一樣,這個 ConstraintSet@id/red_star 中有單一 Constraint。這次將圖片限制在畫面底部。

您不需要為其命名 @id/start@id/end,但命名方式相當方便。

步驟 4:定義轉場效果

每個 MotionScene 也至少必須包含一項轉場效果。轉場效果是指從頭到尾,每個動畫的各個部分。

轉場效果必須指定轉換的開始和結束 ConstraintSet。轉場效果還能指定其他修改動畫的方式,例如動畫的執行時間,或是拖曳檢視畫面的動畫方式。

  1. Motion Editor 在建立 MotionScene 檔案時預設會為我們建立轉場效果。開啟 activity_step1_scene.xml 來查看產生的轉場效果。

activity_step1_scene.xml

<!-- A transition describes an animation via start and end state -->
<Transition
   motion:constraintSetEnd="@+id/end"
   motion:constraintSetStart="@id/start"
   motion:duration="1000">
  <KeyFrameSet>
  </KeyFrameSet>
</Transition>

這就是 MotionLayout 建立動畫所需的一切。查看每個屬性:

  • 系統會在動畫開始時對檢視畫面套用 constraintSetStart
  • 系統會在動畫結束時的檢視畫面套用 constraintSetEnd
  • duration 會指定動畫播放時間 (以毫秒為單位)。

MotionLayout 會找出開始和結束限制之間的路徑,並在指定期間內建立動畫。

步驟 5:在 Motion Editor 中預覽動畫

dff9ecdc1f4a0740.gif

動畫:在 Motion Editor 中播放轉場預覽畫面的影片

  1. 開啟 Motion Editor,然後在總覽面板中按一下 startend 之間的箭頭來選取轉場效果。

1dc541ae8c43b250.png

  1. 選取轉場效果時,「選取」面板會顯示播放控制項和進度控制列。按一下播放或拖曳目前位置即可預覽動畫。

a0fd2593384dfb36.png

步驟 6:新增點擊處理常式

您必須定義動畫的開始播放方式。其中一種做法是讓 MotionLayout 回應 @id/red_star 上的點擊事件。

  1. 開啟動態編輯器,在總覽面板中按一下開始與結尾之間的箭頭,然後選取轉場效果。

b6f94b344ce65290.png

  1. 在總覽面板的工具列中,按一下 699f7ae04024ccf6.png「建立點按或滑動處理常式」。這會新增用來啟動轉場的處理常式。
  2. 在彈出式視窗中選取「Click Handler」

ccf92d06335105fe.png

  1. 將「View To Click」變更為 red_star

b0d3f0c970604f01.png

  1. 按一下「Add」,在 Motion Editor 的轉場效果中會以小點表示。

cec3913e67fb4105.png

  1. 在總覽面板中選取轉場效果後,請將 toggleclickAction 屬性加入剛在屬性面板中新增的 OnClick 處理常式。

9af6fc60673d093d.png

  1. 開啟 activity_step1_scene.xml 即可查看 Motion Editor 產生的程式碼

activity_step1_scene.xml

<!-- A transition describes an animation via start and end state -->
<Transition
    motion:constraintSetStart="@+id/start"
    motion:constraintSetEnd="@+id/end"
    motion:duration="1000">
    <!-- MotionLayout will handle clicks on @id/red_star to "toggle" the animation between the start and end -->
    <OnClick
        motion:targetId="@id/red_star"
        motion:clickAction="toggle" />
</Transition>

Transition 會指示 MotionLayout 使用 <OnClick> 標記執行動畫,回應點擊事件。查看每個屬性:

  • targetId 是點按的檢視畫面。
  • toggleclickAction 會在點擊時切換為開始和結束狀態。您可以在說明文件中查看 clickAction 的其他選項。
  1. 執行程式碼,依序點選「步驟 1」和紅色星號,即可查看動畫!

步驟 5:實際操作動畫

執行應用程式!按一下星號時,您應該就會看到動畫執行了。

(7ba88af963fdfe10.gif)

已完成的動作場景檔案會定義一個 Transition,指向開始和結束的 ConstraintSet

動畫開始 (@id/start) 時,星號圖示限制在畫面頂端的開頭。動畫結束時 (@id/end),星號圖示會顯示在畫面底部。

<?xml version="1.0" encoding="utf-8"?>

<!-- Describe the animation for activity_step1.xml -->
<MotionScene xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:android="http://schemas.android.com/apk/res/android">
   <!-- A transition describes an animation via start and end state -->
   <Transition
           motion:constraintSetStart="@+id/start"
           motion:constraintSetEnd="@+id/end"
           motion:duration="1000">
       <!-- MotionLayout will handle clicks on @id/star to "toggle" the animation between the start and end -->
       <OnClick
               motion:targetId="@id/red_star"
               motion:clickAction="toggle" />
   </Transition>

   <!-- Constraints to apply at the end of the animation -->
   <ConstraintSet android:id="@+id/start">
       <Constraint
               android:id="@+id/red_star"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               motion:layout_constraintStart_toStartOf="parent"
               motion:layout_constraintTop_toTopOf="parent" />
   </ConstraintSet>

   <!-- Constraints to apply at the end of the animation -->
   <ConstraintSet android:id="@+id/end">
       <Constraint
               android:id="@+id/red_star"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               motion:layout_constraintEnd_toEndOf="parent"
               motion:layout_constraintBottom_toBottomOf="parent" />
   </ConstraintSet>
</MotionScene>

4. 根據拖曳事件製作動畫

在這個步驟中,您將建立回應使用者拖曳事件 (使用者滑動畫面時) 的動畫,以執行動畫。MotionLayout 支援追蹤觸控事件來移動檢視畫面,也支援透過物理快速滑過手勢讓動作流暢度。

步驟 1:檢查初始程式碼

  1. 如要開始使用,請開啟含有 MotionLayout 的版面配置檔案 activity_step2.xml。查看程式碼。

activity_step2.xml

<!-- initial code -->

<androidx.constraintlayout.motion.widget.MotionLayout
       ...
       motion:layoutDescription="@xml/step2" >

   <ImageView
           android:id="@+id/left_star"
           ...
   />

   <ImageView
           android:id="@+id/right_star"
           ...
   />

   <ImageView
           android:id="@+id/red_star"
           ...
   />

   <TextView
           android:id="@+id/credits"
           ...
           motion:layout_constraintTop_toTopOf="parent"
           motion:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.motion.widget.MotionLayout>

這個版面配置定義了動畫的所有檢視畫面。三個星號圖示不會在版面配置中受到限制,因為系統會在動態場景中為圖示加上動畫效果。

抵免額 TextView 套用了限制條件,因為在整個動畫中維持不變,且不會修改任何屬性。

步驟 2:為場景製作動畫

和上一個動畫一樣,動畫是由開始和結束的 ConstraintSet,Transition 定義。

定義起始 ConstraintSet

  1. 開啟動態場景 xml/step2.xml 來定義動畫。
  2. 新增起始限制 start 的限制條件。一開始,畫面底部的中心會顯示這三顆星星。左右星號的 alpha 值是 0.0,表示完全透明且隱藏。

step2.xml

<!-- TODO apply starting constraints -->

<!-- Constraints to apply at the start of the animation -->
<ConstraintSet android:id="@+id/start">
   <Constraint
           android:id="@+id/red_star"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           motion:layout_constraintStart_toStartOf="parent"
           motion:layout_constraintEnd_toEndOf="parent"
           motion:layout_constraintBottom_toBottomOf="parent" />

   <Constraint
           android:id="@+id/left_star"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:alpha="0.0"
           motion:layout_constraintStart_toStartOf="parent"
           motion:layout_constraintEnd_toEndOf="parent"
           motion:layout_constraintBottom_toBottomOf="parent" />

   <Constraint
           android:id="@+id/right_star"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:alpha="0.0"
           motion:layout_constraintStart_toStartOf="parent"
           motion:layout_constraintEnd_toEndOf="parent"
           motion:layout_constraintBottom_toBottomOf="parent" />
</ConstraintSet>

在此 ConstraintSet 中,為每個星星指定一個 Constraint。每個限制條件都會在動畫開始時由 MotionLayout 套用。

每個星號檢視都會在畫面底部置中,並使用開始、結束和底部限制。兩顆星 @id/left_star@id/right_star 都有額外的 Alpha 值,因此不會顯示,系統會在動畫開始時套用這個值。

startend 限制可定義動畫的開始和結束。起始限制 (例如 motion:layout_constraintStart_toStartOf) 會限制檢視畫面的開始至另一個檢視畫面的起始位置。這在一開始可能會造成混淆,因為 start 名稱同時用於「而且」在限制條件的情況下使用。為區分差異,layout_constraintStart 中的 start 是指「啟動」也就是由左至右的語言、由右至左的語言呈現。start 限制組合是指動畫的開始時間。

定義結束限制集

  1. 定義結束限制,使用鏈結將全部三顆星放在 @id/credits 下方。此外,它會將左右星號的 alpha 結束值設為 1.0

step2.xml

<!-- TODO apply ending constraints -->

<!-- Constraints to apply at the end of the animation -->
<ConstraintSet android:id="@+id/end">

   <Constraint
           android:id="@+id/left_star"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:alpha="1.0"
           motion:layout_constraintHorizontal_chainStyle="packed"
           motion:layout_constraintStart_toStartOf="parent"
           motion:layout_constraintEnd_toStartOf="@id/red_star"
           motion:layout_constraintTop_toBottomOf="@id/credits" />

   <Constraint
           android:id="@+id/red_star"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           motion:layout_constraintStart_toEndOf="@id/left_star"
           motion:layout_constraintEnd_toStartOf="@id/right_star"
           motion:layout_constraintTop_toBottomOf="@id/credits" />

   <Constraint
           android:id="@+id/right_star"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:alpha="1.0"
           motion:layout_constraintStart_toEndOf="@id/red_star"
           motion:layout_constraintEnd_toEndOf="parent"
           motion:layout_constraintTop_toBottomOf="@id/credits" />
</ConstraintSet>

如此一來,檢視畫面會在動畫中向外擴散,並往中央伸展。

此外,由於兩個 ConstraintSets@id/right_start@id/left_star 都設定了 alpha 屬性,因此兩個檢視畫面都會隨著動畫播放而淡入。

根據使用者滑動操作製作動畫

MotionLayout 可以追蹤使用者拖曳事件 (滑動),建立以物理為基礎的「快速滑過」效果這表示如果使用者快速擲回這些檢視畫面,檢視畫面將會繼續執行,就像移動到表面上的實體物件一樣速度變慢。您可以在 Transition 中使用 OnSwipe 標記新增這種類型的動畫。

  1. 取代 TODO,以 <OnSwipe motion:touchAnchorId="@id/red_star" /> 新增 OnSwipe 標記。

step2.xml

<!-- TODO add OnSwipe tag -->

<!-- A transition describes an animation via start and end state -->
<Transition
       motion:constraintSetStart="@+id/start"
       motion:constraintSetEnd="@+id/end">
   <!-- MotionLayout will track swipes relative to this view -->
   <OnSwipe motion:touchAnchorId="@id/red_star" />
</Transition>

OnSwipe 包含幾個屬性,最重要的是 touchAnchorId

  • touchAnchorId 是回應輕觸的追蹤檢視畫面,MotionLayout 會讓這個檢視畫面與滑動手指的距離相同。
  • touchAnchorSide 會決定要追蹤檢視畫面的哪一側。如果檢視區塊會調整大小、遵循複雜的路徑,或某側移動速度較快,這一點就很重要。
  • dragDirection 會決定動畫的方向 (向上、向下、向左或向右)。

MotionLayout 監聽拖曳事件時,事件監聽器會登錄到 MotionLayout 檢視畫面,而非 touchAnchorId 指定的檢視畫面。當使用者在畫面上的任何位置啟動手勢時,MotionLayout 會維持手指與 touchAnchorId 檢視畫面常數的 touchAnchorSide 之間的距離。舉例來說,如果使用者輕觸與錨點距離 100dp 的距離,在整個動畫中,MotionLayout 都會讓該側與手指保持 100 dp 距離。

立即試用

  1. 再次執行應用程式,然後開啟「步驟 2」畫面。畫面上會顯示動畫。
  2. 嘗試「快速滑過」或放開手指瀏覽動畫,看看 MotionLayout 如何顯示流暢的物理動畫!

fefcdd690a0dcaec.gif

MotionLayout 可以使用 ConstraintLayout 中的功能,在截然不同的設計之間建立動畫效果。

在這段動畫中,畫面底部會顯示這三個檢視畫面,都與其父項檢視畫面相對的位置。最後,三個檢視畫面的位置是相對於鏈結中的 @id/credits

儘管這些版面配置非常不同,MotionLayout 仍會在開始和結束之間建立流暢的動畫。

5. 修改路徑

在這個步驟中,您會建立在動畫播放中依複雜路徑顯示的動畫,並在動作期間以動畫方式呈現功勞。MotionLayout 可以使用 KeyPosition 修改檢視畫面在開始和結束之間的路徑。

步驟 1:探索現有程式碼

  1. 開啟 layout/activity_step3.xmlxml/step3.xml,查看現有的版面配置和動態場景。ImageViewTextView 會顯示月亮和抵免額文字。
  2. 開啟動態場景檔案 (xml/step3.xml)。您會看見從 @id/start@id/endTransition 已定義。動畫使用兩個 ConstraintSets,將月亮圖片從螢幕左下角移至畫面右下方。抵免額的移動時,抵免額文字會從 alpha="0.0" 淡出至 alpha="1.0"
  3. 執行應用程式,然後選取「步驟 3」。按一下月亮時,您會看到月球從起點到終點的線性路徑 (或直線)。

步驟 2:啟用路徑偵錯功能

在將弧形新增至月球運動之前,建議您在 MotionLayout 中啟用路徑偵錯功能。

您可以利用 MotionLayout 繪製每個檢視畫面的動畫路徑,協助開發複雜的動畫。如果您想以視覺化方式呈現動畫,或微調動態的小細節,這項功能就很實用。

  1. 如要啟用偵錯路徑,請開啟 layout/activity_step3.xml 並將 motion:motionDebug="SHOW_PATH" 新增至 MotionLayout 標記。

activity_step3.xml

<!-- Add motion:motionDebug="SHOW_PATH" -->

<androidx.constraintlayout.motion.widget.MotionLayout
       ...
       motion:motionDebug="SHOW_PATH" >

啟用路徑偵錯後,當您再次執行應用程式時,您將會看到所有檢視畫面的路徑,這些路徑都以虛線顯示。

23bbb604f456f65c.png

  • 圓形表示每個檢視畫面的開始或結束位置。
  • 線條代表單一檢視畫面的路徑。
  • 「鑽石」代表修改路徑的 KeyPosition

以此動畫為例,中間圓圈是指抵免額文字的位置。

步驟 3:修改路徑

MotionLayout 中的所有動畫都是由開始和結束的 ConstraintSet 定義,這個物件可定義動畫開始播放前和動畫結束後的畫面。根據預設,MotionLayout 會在每個變更位置時,繪製開始與結束位置之間的線性路徑 (直線)。

如要建構此範例中的月球弧形等複雜路徑,MotionLayout 會使用 KeyPosition 修改檢視區塊在開始和結束之間移動的路徑。

  1. 開啟 xml/step3.xml,並將 KeyPosition 新增至場景。KeyPosition 標記位於 Transition 標記內。

eae4dae9a12d0410.png

step3.xml

<!-- TODO: Add KeyFrameSet and KeyPosition -->
<KeyFrameSet>
   <KeyPosition
           motion:framePosition="50"
           motion:motionTarget="@id/moon"
           motion:keyPositionType="parentRelative"
           motion:percentY="0.5"
   />
</KeyFrameSet>

KeyFrameSetTransition 的子項,也是轉換期間應套用的所有 KeyFrames 組合 (例如 KeyPosition)。

由於 MotionLayout 會計算開始與結束之間的月亮路徑,因此會根據 KeyFrameSet 中指定的 KeyPosition 修改路徑。您可以再次執行應用程式,看看此舉如何修改路徑。

KeyPosition 具有多個屬性,說明其如何修改路徑。最重要的是:

  • framePosition 是介於 0 到 100 之間的數字。這會定義在動畫中套用此 KeyPosition 的時機,其中 1 為 1% 的整個動畫,以及 99 到 99% 的動畫。所以如果值是 50,就應該在中間套用。
  • motionTarget 是此 KeyPosition 修改路徑的檢視畫面。
  • KeyPosition 是如何修改路徑的 keyPositionType。可以是 parentRelativepathRelativedeltaRelative (如下一個步驟所述)。
  • percentX | percentY 是要在 framePosition 修改路徑的程度 (介於 0.0 至 1.0 之間的值,可以為負值且值大於 1)。

您可以這樣想:「在 framePosition 修改路徑:framePosition 修改路徑,修改方式是 percentX ,或percentY 根據 keyPositionType 決定的座標修改路徑」。motionTarget

根據預設,MotionLayout 會將修改路徑後引進的任何邊角四捨五入。當您看剛剛建立的動畫時,可以看到月球跟在彎曲的彎曲路徑上。對多數動畫來說,這是你想要的內容;如果沒有,你可以指定 curveFit 屬性來自訂動畫。

馬上試試

如果您再次執行應用程式,就會看到這個步驟的動畫。

46b179c01801f19e.gif

月球緊隨弧形,因為它會通過 Transition 中指定的 KeyPosition

<KeyPosition
       motion:framePosition="50"
       motion:motionTarget="@id/moon"
       motion:keyPositionType="parentRelative"
       motion:percentY="0.5"
/>

您可以將此 KeyPosition 解讀為:「在 framePosition 50 時 (動畫中半段),根據 parentRelative (整個 MotionLayout) 決定的座標,由 50% Y 移動 motionTarget @id/moon 的路徑 (對畫面的半下方) 修改 motionTarget @id/moon 的路徑。」

因此,在動畫中途,月亮必須通過畫面下 50% 的 KeyPosition。此 KeyPosition 完全不會修改 X 動作,因此月亮仍會從開始到結束橫向。MotionLayout 會找出通過這個 KeyPosition,同時在開始和結束之間移動的順暢路徑。

如果仔細觀察,作者資訊文字就會受到月亮位置的限制。為什麼不垂直移動?

1c7cf779931e45cc.gif

<Constraint
       android:id="@id/credits"
       ...
       motion:layout_constraintBottom_toBottomOf="@id/moon"
       motion:layout_constraintTop_toTopOf="@id/moon"
/>

就算您修改了月球的行經路徑,月亮的起點和終點卻還是沒有垂直移動。KeyPosition 不會修改開始或結束位置,因此抵免額文字僅限於月球的最終結束位置。

如果想隨著抵免額隨著月亮移動,可以為抵免額新增 KeyPosition,或是修改 @id/credits 的起始限制。

下一節將深入說明 MotionLayout 中不同類型的 keyPositionType

6. 瞭解 keyPositionType

在上一個步驟中,您使用了 parentRelativekeyPosition 類型,將路徑偏移至螢幕的 50%。屬性 keyPositionType 會決定 MotionLayout 根據 percentXpercentY 修改路徑的「方式」

<KeyFrameSet>
   <KeyPosition
           motion:framePosition="50"
           motion:motionTarget="@id/moon"
           motion:keyPositionType="parentRelative"
           motion:percentY="0.5"
   />
</KeyFrameSet>

可用的 keyPosition 分為三種類型:parentRelativepathRelativedeltaRelative。指定類型會變更計算 percentXpercentY 時使用的座標系統。

什麼是座標系統?

「座標系統」可用於在空間中指定點。這些註解也可用來描述畫面上的位置。

MotionLayout 座標系統屬於購物車座標系統。也就是有 X 軸和 Y 軸,並由兩條垂直線定義。兩者的主要差異在於 X 軸在畫面上的位置 (Y 軸一律與 X 軸垂直)。

MotionLayout 中的所有座標系統都會在 X 和 Y 軸上使用 0.01.0 之間的值。可使用負值和大於 1.0 的值。舉例來說,如果 percentX 值為 -2.0,就代表 X 軸的相反方向。

如果您覺得「代數課程」聽起來太過緊張,請查看下方的圖片!

父項座標

a7b7568d46d9dec7.png

parentRelativekeyPositionType 使用與螢幕相同的座標系統。這可將 (0, 0) 定義在整個 MotionLayout 的左上方,並將 (1, 1) 定義在右下方。

您可以隨時使用 parentRelative 製作會穿過整個 MotionLayout 的動畫 (如這個範例中的月球弧形)。

然而,如果您想要修改相對於動態的路徑,例如讓它稍微呈現曲線,則其他兩個座標系統是更好的選擇。

差異座標

5680bf553627416c.png

差異值是「變化」的數學詞,所以 deltaRelative 是「相對改變」的方式。在 deltaRelative 座標(0,0)中,檢視畫面的起始位置,(1,1) 則是結束位置。X 和 Y 軸對齊畫面。

螢幕上的 X 軸一律為水平,Y 軸則一律為垂直畫面。與 parentRelative 相比,主要差別在於座標僅代表畫面移動檢視畫面的部分。

deltaRelative 是絕佳的座標系統,可以單獨控制水平或垂直動作。舉例來說,您可以建立動畫,使其在 50% 處完成垂直 (Y) 移動,然後繼續水平 (X) 動畫。

庫存座標

f3aaadaac8b4a93f.png

MotionLayout 中的最後一個座標系統是 pathRelative。X 軸會隨開始到結束的動態路徑,因此也與另外兩軸截然不同。因此,(0,0) 是起始位置,(1,0) 則是結束位置。

你為什麼想這麼做?乍看之下相當令人驚訝,尤其是因為這個座標系統甚至並未對齊螢幕座標。

結果顯示,pathRelative 非常適合用於下列功能。

  • 在部分動畫過程中加速、減速或停止檢視畫面。由於 X 維度一律與檢視畫面採用的路徑完全相符,因此您可以使用 pathRelative KeyPosition 變更路徑中特定點的 framePosition。因此,在 framePosition="50" 搭配 percentX="0.1"KeyPosition,會導致動畫在前 10% 運動時間佔 50% 的時間。
  • 在路徑中加入細微的弧線。Y 維度總是與動態垂直,因此變更 Y 會將路徑改成相對於整體動作的曲線。
  • deltaRelative 無法運作時新增第二個維度。如果是完全水平和垂直的動作,deltaRelative 只會建立一個實用的維度。不過,pathRelative 一律會建立可用的 X 和 Y 座標。

在下一個步驟中,您將瞭解如何使用多個 KeyPosition 建構更複雜的路徑。

7. 建立複雜路徑

檢視您在上個步驟建立的動畫,確實會形成平滑曲線,但形狀可能會比較像是「喜歡月亮」。

修改包含多個 KeyPosition 元素的路徑

MotionLayout 可以進一步定義任何動作所需的 KeyPosition,藉此進一步修改路徑。在這個動畫中,您將建立一個弧形,但您可以視需要在畫面中間上下跳動。

  1. 開啟 xml/step4.xml。您會看到這個檢視畫面與上個步驟新增的 KeyFrame 相同。
  2. 如要將曲線的頂端納入圓滑邊緣,請在 @id/moon 的路徑中再加入兩個 KeyPositions,一個在到達頂端之前,一個在路徑頂端。

500b5ac2db48ef87.png

step4.xml

<!-- TODO: Add two more KeyPositions to the KeyFrameSet here -->
<KeyPosition
       motion:framePosition="25"
       motion:motionTarget="@id/moon"
       motion:keyPositionType="parentRelative"
       motion:percentY="0.6"
/>
<KeyPosition
       motion:framePosition="75"
       motion:motionTarget="@id/moon"
       motion:keyPositionType="parentRelative"
       motion:percentY="0.6"
/>

這些 KeyPositions 會套用動畫效果的 25% 和 75%,並導致 @id/moon 沿著與畫面頂端 60% 距離的路徑移動。與現有 KeyPosition 的 50% 結合之後,即可創造出平滑的月球。

MotionLayout 中,您可以視需求新增任意數量的 KeyPositions,以便取得所需動態路徑。MotionLayout 會在指定的 framePosition 中套用每個 KeyPosition,並設法建立通過所有 KeyPositions 的流暢動作。

馬上試試

  1. 再次執行應用程式。前往步驟 4 觀看動畫的實際效果。按一下月亮時,系統會從頭到尾依序瀏覽路徑,瀏覽在 KeyFrameSet 中指定的每個 KeyPosition

自行探索

開始使用其他類型的 KeyFrame 前,請先嘗試在 KeyFrameSet 中新增更多 KeyPositions,看看只要使用 KeyPosition 即可建立什麼效果。

以下的例子說明如何建構可在動畫過程中來回移動的複雜路徑。

cd9faaffde3dfef.png

step4.xml

<!-- Complex paths example: Dancing moon -->
<KeyFrameSet>
   <KeyPosition
           motion:framePosition="25"
           motion:motionTarget="@id/moon"
           motion:keyPositionType="parentRelative"
           motion:percentY="0.6"
           motion:percentX="0.1"
   />
   <KeyPosition
           motion:framePosition="50"
           motion:motionTarget="@id/moon"
           motion:keyPositionType="parentRelative"
           motion:percentY="0.5"
           motion:percentX="0.3"
   />
   <KeyPosition
           motion:framePosition="75"
           motion:motionTarget="@id/moon"
           motion:keyPositionType="parentRelative"
           motion:percentY="0.6"
           motion:percentX="0.1"
   />
</KeyFrameSet>

瞭解 KeyPosition 的各項功能後,您就可以在下一個步驟中繼續進行其他類型的 KeyFrames

8. 在動作期間變更屬性

建立動態動畫通常意味著隨著動畫進度而變更檢視畫面的 sizerotationalphaMotionLayout 支援使用 KeyAttribute,在任何檢視畫面上為許多屬性建立動畫效果。

在這個步驟中,您將使用 KeyAttribute 縮放月亮並旋轉。您也會使用 KeyAttribute 延後文字外觀,直到月球快遞完成為止。

步驟 1:使用 KeyAttribute 調整大小和旋轉

  1. 開啟 xml/step5.xml,其中包含您在上個步驟中建立的相同動畫。為方便起見,這個畫面會使用其他空間相片做為背景。
  2. 如要將月亮放大並旋轉,請在 KeyFrameSetkeyFrame="50"keyFrame="100" 中加入兩個 KeyAttribute 標記

bbae524a2898569.png

step5.xml

<!-- TODO: Add KeyAttributes to rotate and resize @id/moon -->

<KeyAttribute
       motion:framePosition="50"
       motion:motionTarget="@id/moon"
       android:scaleY="2.0"
       android:scaleX="2.0"
       android:rotation="-360"
/>
<KeyAttribute
       motion:framePosition="100"
       motion:motionTarget="@id/moon"
       android:rotation="-720"
/>

這些 KeyAttributes 會套用動畫的 50% 和 100%。第一個是 50% 的 KeyAttribute 發生在弧形頂部,這會使檢視畫面在大小上加倍,同時旋轉 -360 度 (或一個圓形)。第二個 KeyAttribute 會將第二次旋轉至 -720 度 (兩個完整的圓圈),並將大小放回一般,因為 scaleXscaleY 的值預設為 1.0。

KeyPosition 一樣,KeyAttribute 會使用 framePositionmotionTarget 指定套用 KeyFrame 的時機和修改檢視畫面。MotionLayout 會在 KeyPositions 之間插入內插,建立流暢動畫。

KeyAttributes 支援可套用至所有資料檢視的屬性。支援變更基本屬性,例如 visibilityalphaelevation。您也可以像在這裡一樣變更旋轉角度、使用 rotateXrotateY 旋轉三個尺寸、使用 scaleXscaleY 縮放大小,或者轉換檢視畫面在 X、Y 或 Z 中的位置。

步驟 2:延遲發放抵免額

這個步驟的目標之一是更新動畫,讓製作人員名單文字要等到動畫播放完畢後才顯示。

  1. 如要延遲抵免額出現,請再定義一個 KeyAttribute,確保 alphakeyPosition="85" 前會維持在 0。MotionLayout 仍可從 0 到 100 alpha 順暢地轉換,但會沿著動畫最後 15% 的進度執行。

step5.xml

<!-- TODO: Add KeyAttribute to delay the appearance of @id/credits -->

<KeyAttribute
       motion:framePosition="85"
       motion:motionTarget="@id/credits"
       android:alpha="0.0"
/>

這個 KeyAttribute 會在前 85% 動畫的前 85% 中,將 @id/creditsalpha 維持在 0.0。由於一開始的 Alpha 值為 0,因此會在動畫的前 85% 不會顯示。

KeyAttribute 的最終效果是製作人員名單顯示在動畫的結尾處。如此一來,介面的外觀就會與畫面右上角的月亮協調相協調。

藉由延遲一個檢視畫面上的動畫,而另一個檢視畫面移動的情形可像此一樣,您可以建立令人印象深刻的動畫,為使用者的動態效果。

馬上試試

  1. 再次執行應用程式,然後前往步驟 5,查看動畫的實際效果。點選月球後,系統會按照從開始到結束的路徑逐一瀏覽在 KeyFrameSet 中指定的 KeyAttribute

2f4bfdd681c1fa98.gif

由於您旋轉了月亮兩個完全圓圈,所以現在會重複向後翻轉,而且製作人員會延遲顯示動畫,直到動畫結束為止。

自行探索

請先嘗試修改 KeyAttributes 中的其他標準屬性,再前往最終的 KeyFrame 類型。舉例來說,請嘗試將 rotation 變更為 rotationX,看看其產生的動畫。

下列是您可以嘗試的標準屬性清單:

  • android:visibility
  • android:alpha
  • android:elevation
  • android:rotation
  • android:rotationX
  • android:rotationY
  • android:scaleX
  • android:scaleY
  • android:translationX
  • android:translationY
  • android:translationZ

9. 變更自訂屬性

豐富的動畫涉及變更檢視畫面的顏色或其他屬性。雖然 MotionLayout 可以使用 KeyAttribute 變更上一個工作中列出的任何標準屬性,但您也可以使用 CustomAttribute 指定任何其他屬性。

CustomAttribute 可用於設定具有 setter 的任何值。舉例來說,您可以使用 CustomAttribute 設定 View 的 backgroundColorMotionLayout 會使用「反射」尋找 setter,然後重複呼叫,為檢視畫面建立動畫效果。

在這個步驟中,您將使用 CustomAttribute 設定月球上的 colorFilter 屬性,建立下方顯示的動畫。

5fb6792126a09fda.gif

定義自訂屬性

  1. 如要開始使用,請開啟 xml/step6.xml,其中包含您在上個步驟中建立的相同動畫。
  2. 如要將月亮變色,請在 KeyFrameSetkeyFrame="0"keyFrame="50"keyFrame="100". 中新增兩個含有 CustomAttributeKeyAttribute

214699d5fdd956da.png

step6.xml

<!-- TODO: Add Custom attributes here -->
<KeyAttribute
       motion:framePosition="0"
       motion:motionTarget="@id/moon">
   <CustomAttribute
           motion:attributeName="colorFilter"
           motion:customColorValue="#FFFFFF"
   />
</KeyAttribute>
<KeyAttribute
       motion:framePosition="50"
       motion:motionTarget="@id/moon">
   <CustomAttribute
           motion:attributeName="colorFilter"
           motion:customColorValue="#FFB612"
   />
</KeyAttribute>
<KeyAttribute
       motion:framePosition="100"
       motion:motionTarget="@id/moon">
   <CustomAttribute
           motion:attributeName="colorFilter"
           motion:customColorValue="#FFFFFF"
   />
</KeyAttribute>

您會在 KeyAttribute 中新增 CustomAttributeCustomAttribute 會在 KeyAttribute 指定的 framePosition 套用。

CustomAttribute 中,必須指定 attributeName 和一個要設定的值。

  • motion:attributeName 是此自訂屬性將呼叫的 setter 名稱。在這個範例中,系統會呼叫 Drawable 上的 setColorFilter
  • motion:custom*Value 是名稱中註明的類型自訂值,在此範例中,自訂值是指定的顏色。

自訂值可以是下列任一種類型:

  • 顏色
  • 整數
  • 浮點值
  • 字串
  • 維度
  • 布林值

使用這個 API,MotionLayout 可為任何檢視畫面提供 setter 的任何內容加上動畫效果。

馬上試試

  1. 再次執行應用程式,然後前往步驟 6,查看動畫的實際效果。點選月球後,系統會按照從開始到結束的路徑逐一瀏覽在 KeyFrameSet 中指定的 KeyAttribute

5fb6792126a09fda.gif

新增更多 KeyFrames 時,MotionLayout 會將月亮路徑從直線變更為複雜的曲線,在動畫中增加雙向翻轉、調整大小,以及變更色彩。

在真實動畫中,您通常可以同時為數個檢視畫面建立動畫,並控制這些檢視畫面在不同路徑和速度上的動作。透過為每個檢視畫面指定不同的 KeyFrame,即可利用 MotionLayout 編排多媒體動畫,建立動畫效果的多個檢視畫面。

10. 拖曳事件和複雜的路徑

在這個步驟中,您將瞭解如何使用包含複雜路徑的 OnSwipe。到目前為止,OnClick 事件監聽器觸發了月亮動畫,且執行時間固定。

使用 OnSwipe 控制含有複雜路徑的動畫 (例如您在最後幾個步驟中建立的月亮動畫),需要瞭解 OnSwipe 的運作方式。

步驟 1:瞭解 OnSwipe 行為

  1. 開啟 xml/step7.xml 並找出現有的 OnSwipe 宣告。

step7.xml

<!-- Fix OnSwipe by changing touchAnchorSide 

<OnSwipe
       motion:touchAnchorId="@id/moon"
       motion:touchAnchorSide="bottom"
/>
  1. 在裝置上執行應用程式,然後前往步驟 7。沿著弧形路徑拖曳月亮,看看是否能產生流暢的動畫。

執行這個動畫時,看起來不會很滿意。月球到達弧形頂端後,就會開始跳動。

ed96e3674854a548.gif

如要瞭解錯誤,請考慮使用者輕觸弧形頂端下方時會發生什麼事。由於 OnSwipe 標記包含 motion:touchAnchorSide="bottom" MotionLayout,系統會嘗試在整個動畫期間,讓手指與檢視畫面常數之間的距離保持不變。

但是,由於月亮底部的方向不一定相同,因此圖示會往上回升,因此 MotionLayout 不知道使用者剛通過弧形頂部時該怎麼做。既然如此,由於你正在追蹤月亮底部,因此使用者輕觸這裡時,應該把它擺放在哪個位置?

56cd575c5c77eddd.png

步驟 2:使用右側

為避免這類錯誤,請務必選擇在整個動畫播放期間一律朝同一方向的 touchAnchorIdtouchAnchorSide

在這個動畫中,right 側和月亮 left 側都會在螢幕上朝某個方向前進。

但是,bottomtop 都會反向方向。當 OnSwipe 嘗試追蹤這些線索時,如果方向改變,就會混淆。

  1. 如要讓此動畫追蹤觸控事件,請將 touchAnchorSide 變更為 right

step7.xml

<!-- Fix OnSwipe by changing touchAnchorSide 

<OnSwipe
       motion:touchAnchorId="@id/moon"
       motion:touchAnchorSide="right"
/>

步驟 3:使用 DragDirection

您也可以將 dragDirectiontouchAnchorSide 結合,讓側軌和一般的方向不同。仍需讓 touchAnchorSide 只往一個方向進行,但您可以告知 MotionLayout 要追蹤的方向。舉例來說,您可以保留 touchAnchorSide="bottom",但新增 dragDirection="dragRight"。這會讓 MotionLayout 追蹤檢視畫面底部的位置,但只在向右移動時考慮其位置 (會忽略垂直動作)。因此,即使底部上下顛倒,仍會搭配 OnSwipe 正確播放動畫。

  1. 更新 OnSwipe 即可正確追蹤月亮運動。

step7.xml

<!-- Using dragDirection to control the direction of drag tracking 

<OnSwipe
       motion:touchAnchorId="@id/moon"
       motion:touchAnchorSide="bottom"
       motion:dragDirection="dragRight"
/>

馬上試試

  1. 請再次執行應用程式,然後試著將月球拖曳到整個路徑。雖然採用複雜的弧線,但 MotionLayout 能夠回應滑動事件的動畫。

5458dff382261427.gif

11. 透過程式碼跑步

CoordinatorLayout 搭配使用時,MotionLayout 可用於建構豐富的動畫。在這個步驟中,您將使用 MotionLayout 建立可收合標頭。

步驟 1:探索現有程式碼

  1. 如要開始使用,請開啟「layout/activity_step8.xml」。
  2. layout/activity_step8.xml 中,您會看到已建構運作中的 CoordinatorLayoutAppBarLayout

activity_step8.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout
       ...>
   <com.google.android.material.appbar.AppBarLayout
           android:id="@+id/appbar_layout"
           android:layout_width="match_parent"
           android:layout_height="180dp">
       <androidx.constraintlayout.motion.widget.MotionLayout
               android:id="@+id/motion_layout"
               ... >
           ...
       </androidx.constraintlayout.motion.widget.MotionLayout>
   </com.google.android.material.appbar.AppBarLayout>
  
   <androidx.core.widget.NestedScrollView
           ...
           motion:layout_behavior="@string/appbar_scrolling_view_behavior" >
           ...
   </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

此版面配置使用 CoordinatorLayoutNestedScrollViewAppBarLayout 之間共用捲動資訊。因此,當 NestedScrollView 向上捲動時,會向 AppBarLayout 告知變更。這就是在 Android 上實作類似收合工具列的方式,而文字的捲動將會「協調」與收合標題相同

@id/motion_layout 指向的動作場景與最後一個步驟中的動態場景相似。不過,為了與 CoordinatorLayout 搭配使用,系統已移除 OnSwipe 宣告。

  1. 執行應用程式,然後前往步驟 8。您會發現,捲動文字時,月亮並不會移動。

步驟 2:讓 MotionLayout 捲動

  1. 如要讓 MotionLayout 檢視畫面在 NestedScrollView 捲動時立即捲動,請在 MotionLayout 中加入 motion:minHeightmotion:layout_scrollFlags

activity_step8.xml

<!-- Add minHeight and layout_scrollFlags to the MotionLayout -->

<androidx.constraintlayout.motion.widget.MotionLayout
       android:id="@+id/motion_layout"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       motion:layoutDescription="@xml/step8"
       motion:motionDebug="SHOW_PATH"
       android:minHeight="80dp"
       motion:layout_scrollFlags="scroll|enterAlways|snap|exitUntilCollapsed"  >
  1. 再次執行應用程式,然後前往步驟 8。您會發現,MotionLayout 會在您向上捲動時收合。不過,動畫尚未根據捲動行為進度。

步驟 3:透過程式碼移動動態

  1. 開啟 Step8Activity.kt。編輯 coordinateMotion() 函式,告知 MotionLayout 捲動位置的變化。

Step8Activity.kt

// TODO: set progress of MotionLayout based on an AppBarLayout.OnOffsetChangedListener

private fun coordinateMotion() {
    val appBarLayout: AppBarLayout = findViewById(R.id.appbar_layout)
    val motionLayout: MotionLayout = findViewById(R.id.motion_layout)

    val listener = AppBarLayout.OnOffsetChangedListener { unused, verticalOffset ->
        val seekPosition = -verticalOffset / appBarLayout.totalScrollRange.toFloat()
        motionLayout.progress = seekPosition
    }

    appBarLayout.addOnOffsetChangedListener(listener)
}

此程式碼會註冊一個 OnOffsetChangedListener,每當使用者以目前的捲動偏移方式捲動網頁時,就會呼叫這個程式碼。

MotionLayout 支援透過設定進度屬性尋找轉場效果。如要在 verticalOffset 和百分比進度之間轉換,請將捲動總範圍除以總捲動範圍。

馬上試試

  1. 再次部署應用程式,然後執行「步驟 8」動畫。您會看到 MotionLayout 會根據捲動位置播放動畫。

ee5ce4d9e33a59ca.gif

您可以使用 MotionLayout 建構自訂動態收合工具列動畫。使用一系列的 KeyFrames 可以創造非常大膽的效果。

12. 恭喜

本程式碼研究室涵蓋了 MotionLayout 的基本 API。

如要查看更多 MotionLayout 實務範例,請參閱官方範例。請務必詳閱說明文件

瞭解詳情

MotionLayout 支援更多本程式碼研究室未涵蓋的功能,例如可讓您以重複週期控制路徑或屬性的 KeyCycle,,以及可讓您根據時鐘時間製作動畫的 KeyTimeCycle,。請參考範例。

如需本課程其他程式碼研究室的連結,請參閱「Android Kotlin 的進階程式碼研究室到達網頁」連結。