1. 始める前に
この Codelab は「Kotlin による高度な Android」コースの一部です。このコースは、Codelab を順番に進めることで最大限に活用できますが、必須ではありません。コースのすべての Codelab は、Kotlin を使用した高度な Android Codelab のランディング ページに掲載されています。
MotionLayout
は、Android アプリにリッチ モーションを追加できるライブラリです。ConstraintLayout,
に基づいており、ConstraintLayout
を使用してビルドできるものをすべてアニメーション化できます。
MotionLayout
を使用すると、複数のビューの位置、サイズ、可視性、アルファ、色、高度、回転などの属性を同時にアニメーション化できます。宣言型 XML を使用すると、コードでは実現が困難な、複数のビューを含む調整されたアニメーションを作成できます。
アニメーションはアプリのエクスペリエンスを強化する優れた方法です。アニメーションを使用して次のことができます。
- 変更を表示する - 状態を切り替えることで、ユーザーが UI の変化を自然に追跡できるようにします。
- 注意を引く - アニメーションを使用して重要な UI 要素に注意を引くことができます。
- 美しいデザインの作成 - 効果的な動きによってアプリを洗練されたものにできます。
前提条件
この Codelab は、Android での開発経験があるデベロッパーを対象としています。この Codelab を始める前に、次のことを行う必要があります。
- アクティビティと基本的なレイアウトを含むアプリを作成し、Android Studio を使用してデバイスまたはエミュレータで実行する方法について説明します。
ConstraintLayout
について十分に理解してください。ConstraintLayout
の詳細については、制約レイアウトの Codelab をご覧ください。
演習内容
ConstraintSets
とMotionLayout
を使用してアニメーションを定義する- ドラッグ イベントに基づいてアニメーション化する
KeyPosition
でアニメーションを変更するKeyAttribute
で属性を変更する- コードを使用してアニメーションを実行する
MotionLayout
で折りたたみ可能なヘッダーをアニメーション化する
必要なもの
- Android Studio 4.0(
MotionLayout
エディタは、このバージョンの Android Studio でのみ動作します)
2. はじめに
サンプルアプリを次のいずれかの方法でダウンロードします。
または次のコマンドを使用して、コマンドラインから GitHub リポジトリのクローンを作成します。
$ git clone https://github.com/googlecodelabs/motionlayout.git
3. MotionLayout を使用してアニメーションを作成する
まず、ユーザーのクリックに反応してビューが画面の上端から下端に移動するアニメーションを作成します。
スターター コードからアニメーションを作成するには、次の主要な要素が必要です。
ConstraintLayout
のサブクラスであるMotionLayout,
。アニメーション化するすべてのビューをMotionLayout
タグ内に指定します。MotionScene,
。MotionLayout.
のアニメーションを記述する XML ファイルです。MotionScene
の一部であるTransition,
。アニメーションの持続時間、トリガー、ビューの移動方法を指定します。- 遷移の「開始」制約と「終了」制約の両方を指定する
ConstraintSet
。
それでは、MotionLayout
から順に、それぞれについて見ていきましょう。
ステップ 1: 既存のコードを確認する
MotionLayout
は ConstraintLayout
のサブクラスであるため、アニメーションを追加する際に同じ機能をすべてサポートします。MotionLayout
を使用するには、ConstraintLayout.
を使用する MotionLayout
ビューを追加します。
res/layout
でactivity_step1.xml.
を開きます。ここでは、内部に色合いが適用された星のImageView
が 1 つあるConstraintLayout
があります。
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
に変換する必要があります。
レイアウトでモーション シーンを使用するには、シーンを指す必要があります。
- そのためには、デザイン サーフェスを開きます。Android Studio 4.0 では、レイアウト XML ファイルを表示する際に、右上にある分割アイコンまたはデザイン アイコンを使用してデザイン サーフェスを開きます。
- デザイン サーフェスを開いたら、プレビューを右クリックして [Convert to MotionLayout] を選択します。
これにより、ConstraintLayout
タグが MotionLayout
タグに置き換えられ、@xml/activity_step1_scene.
を指す motion:layoutDescription
が 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 が表示されます。
Motion Editor には、次の 3 つの新しい UI 要素があります。
- [概要] – アニメーションのさまざまな部分を選択できるモーダル選択です。この画像では、
start
ConstraintSet
が選択されています。start
とend
の間の矢印をクリックして、切り替え効果を選択することもできます。 - Section – 概要の下にはセクション ウィンドウがあり、現在選択されている概要アイテムに応じて変わります。この画像では、選択ウィンドウに
start
ConstraintSet
情報が表示されています。 - Attribute – 属性パネルが表示され、現在選択されているアイテムの属性を概要ウィンドウまたは選択ウィンドウから編集できます。この画像では、
start
ConstraintSet
の属性が示されています。
ステップ 3: 開始制約と終了制約を定義する
すべてのアニメーションは、開始と終了の観点から定義できます。start はアニメーション前の画面の様子を示し、end はアニメーションが完了した後の画面を示しています。MotionLayout
は、開始状態と終了状態の間で(時間の経過に伴って)アニメーション化する方法を決定します。
MotionScene
は、ConstraintSet
タグを使用して開始状態と終了状態を定義します。ConstraintSet
はその名のとおり、ビューに適用できる一連の制約です。これには、幅、高さ、ConstraintLayout
の制約が含まれます。また、alpha
などの属性も含まれます。これには、ビュー自体は含まれず、それらのビューに対する制約だけが含まれます。
ConstraintSet
で指定した制約は、レイアウト ファイルで指定された制約をオーバーライドします。レイアウトと MotionScene
の両方で制約を定義すると、MotionScene
の制約のみが適用されます。
このステップでは、スタービューの開始位置が画面の上端から開始し、終了位置が画面の下端に制限されるようにします。
この手順は、Motion Editor を使用するか、activity_step1_scene.xml
のテキストを直接編集して完了できます。
- 概要パネルで
start
ConstraintSet を選択します。
- [選択] パネルで、
red_star
を選択します。現在、layout
のソースが表示されています。これは、このConstraintSet
で制約されていないことを意味します。右上の鉛筆アイコンを使用して、[制約を作成] をクリックします。
- 概要パネルで
start
ConstraintSet
が選択されたときに、red_star
にstart
のソースが表示されることを確認します。 - [Attributes] パネルで、
start
ConstraintSet
でred_star
を選択した状態で、上部に制約を追加し、青い [+] ボタンをクリックします。
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>
ConstraintSet
の id
は @id/start
であり、MotionLayout
内のすべてのビューに適用するすべての制約を指定します。この MotionLayout
にはビューが 1 つしかないため、必要な Constraint
は 1 つだけです。
ConstraintSet
内の Constraint
は、制約するビューの ID(activity_step1.xml
で定義された @id/red_star
)を指定します。Constraint
タグは制約とレイアウト情報のみを指定することに注意してください。Constraint
タグは、ImageView
に適用されていることを認識しません。
この制約では、高さ、幅、および red_star
ビューを親の最上部の端に制約するために必要な他の 2 つの制約を指定します。
- 概要パネルで
end
ConstraintSet を選択します。
- 以前と同じ手順に沿って、
end
のConstraintSet
でred_star
のConstraint
を追加します。 - Motion Editor を使用してこのステップを完了するには、青色の + ボタンをクリックして、
bottom
とend
に制約を追加します。
- 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
に 1 つの Constraint
があります。今度は画面の下端に固定されます。
@id/start
や @id/end
という名前を付ける必要はありませんが、そうすると便利です。
ステップ 4: 遷移を定義する
また、すべての MotionScene
には、少なくとも 1 つの遷移を含める必要があります。遷移は、開始から終了まで、1 つのアニメーションのすべての部分を定義します。
遷移の開始と終了の ConstraintSet
を指定する必要があります。遷移では、他の方法でアニメーションをどのように変更するか(アニメーションの実行時間や、ビューをドラッグしてアニメーション化する方法など)を指定することもできます。
- 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 でアニメーションをプレビューする
アニメーション: Motion Editor で切り替え効果のプレビューを再生する動画
- Motion Editor を開き、概要パネルで
start
とend
の間の矢印をクリックして切り替え効果を選択します。
- 選択パネルには、切り替え効果を選択すると、再生コントロールとスクラブバーが表示されます。再生をクリックするか、現在の位置をドラッグしてアニメーションをプレビューします。
ステップ 6: クリック時ハンドラを追加する
アニメーションを開始する手段が必要です。その方法の 1 つは、MotionLayout
が @id/red_star
でのクリック イベントに応答するようにすることです。
- モーション エディタを開き、概要パネルの開始と終了の間にある矢印をクリックして切り替え効果を選択します。
- 概要パネルのツールバーで、[ クリック ハンドラまたはスワイプ ハンドラを作成] をクリックします。これにより、遷移を開始するハンドラが追加されます。
- ポップアップから [クリック ハンドラ] を選択します。
- [View To Click] を
red_star
に変更します。
- [Add] をクリックすると、クリック ハンドラが Motion Editor の [トランジション] に小さな点で表示されます。
- 概要パネルで遷移を選択したら、先ほど属性パネルに追加した OnClick ハンドラに
toggle
のclickAction
属性を追加します。
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
は、<OnClick>
タグを使用して、クリック イベントに応答してアニメーションを実行するよう MotionLayout
に指示します。各属性の確認:
targetId
は、クリックを監視するビューです。toggle
のclickAction
は、クリックすると開始状態と終了状態が切り替わります。clickAction
のその他のオプションについては、ドキュメントをご覧ください。
- コードを実行して [Step 1] をクリックし、赤い星をクリックしてアニメーションを確認します。
ステップ 5: アニメーションの動作
アプリを実行します。星をクリックすると、アニメーションが実行されます。
完成したモーション シーン ファイルは、開始と終了の ConstraintSet
を指す 1 つの Transition
を定義します。
アニメーションの開始時(@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: 初期コードを検査する
- まず、既存の
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>
このレイアウトでは、アニメーションのすべてのビューを定義します。3 つ星のアイコンは、モーション シーンでアニメーション化されるため、レイアウトの制約はありません。
クレジット TextView
には制約が適用されます。これは、アニメーション全体で同じ場所にとどまり、属性を変更しないためです。
ステップ 2: シーンをアニメーション化する
最後のアニメーションと同様に、アニメーションは開始と終了の ConstraintSet,
と Transition
で定義されます。
開始 ConstraintSet を定義します。
- モーション シーン
xml/step2.xml
を開いてアニメーションを定義します。 - 開始制約
start
の制約を追加します。最初は、3 つの星がすべて画面下部の中央に表示されています。右と左の星の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
では、星ごとに 1 つの Constraint
を指定します。各制約は、アニメーションの開始時に MotionLayout
によって適用されます。
各スタービューは、開始、終了、下部の制約を使用して、画面の下部に中央寄せされます。@id/left_star
と @id/right_star
の 2 つの星には、非表示になる追加のアルファ値があり、アニメーションの開始時に適用されます。
start
制約セットと end
制約セットは、アニメーションの開始と終了を定義します。motion:layout_constraintStart_toStartOf
など、開始時の制約は、ビューの開始点を別のビューの開始点に制限します。これは、start
という名前が両方に使用され、かつ両方とも制約のコンテキストで使用されるため、最初は混乱する可能性があります。区別を明確にするために、layout_constraintStart
の start
は「start」を参照しています。ビューでは、左から右に記述する言語、右から左に記述する言語、start
制約セットは、アニメーションの開始を参照します。
終了 ConstraintSet を定義する
- 3 つ星すべてをまとめて
@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>
最終的に、ビューはアニメーションに応じて中央から広く表示されます。
また、alpha
プロパティは両方の ConstraintSets
で @id/right_start
と @id/left_star
に設定されているため、アニメーションが進むにつれて両方のビューがフェードインします。
ユーザーのスワイプに基づくアニメーション化
MotionLayout
は、ユーザーのドラッグ イベント(スワイプ)をトラッキングして、物理ベースの「フリング」を作成できます。作成します。つまり、ユーザーがビューを投げるとビューは動作し続け、物理的な物体のように表面を転がるときのように速度が低下します。このタイプのアニメーションは、Transition
で OnSwipe
タグを使用して追加できます。
OnSwipe
タグを追加する TODO を<OnSwipe motion:touchAnchorId="@id/red_star" />
に置き換えます。
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
がドラッグ イベントをリッスンする場合、リスナーは touchAnchorId
で指定されたビューではなく、MotionLayout
ビューに登録されます。ユーザーが画面上の任意の場所でジェスチャーを開始すると、MotionLayout
は指と touchAnchorId
ビューの touchAnchorSide
との距離を一定に保ちます。たとえば、MotionLayout
は、アンカー側から 100 dp の距離に接触した場合、アニメーション全体で、アンカー側から指から 100 dp の距離を保ちます。
試してみる
- アプリを再度実行し、ステップ 2 の画面を開きます。アニメーションが表示されます。
- 「フリング」と言ってみてくださいまたは、アニメーションの途中で指を離すと、
MotionLayout
で流体物理学ベースのアニメーションがどのように表示されるかを確認できます。
MotionLayout
は、ConstraintLayout
の機能を使用してさまざまなデザインの間でアニメーションを付け、リッチな効果を作成できます。
このアニメーションでは、開始時の画面下部で、3 つのビューすべてが親を基準として配置されます。最後に、3 つのビューは @id/credits
を基準としてチェーン内に配置されます。
このようにレイアウトが大きく異なっていても、MotionLayout
は開始と終了の間に滑らかなアニメーションを作成します。
5. パスの変更
このステップでは、アニメーション中は複雑なパスに沿って、モーション中はクレジットをアニメーション化するアニメーションを作成します。MotionLayout
では、KeyPosition
を使用して、開始から終了までの間にビューが通るパスを変更できます。
ステップ 1: 既存のコードを確認する
layout/activity_step3.xml
とxml/step3.xml
を開き、既存のレイアウトとモーションシーンを表示します。ImageView
とTextView
は、月とクレジットのテキストを表示します。- モーション シーン ファイル(
xml/step3.xml
)を開きます。@id/start
から@id/end
までのTransition
が定義されていることがわかります。このアニメーションでは、2 つのConstraintSets
を使用して、月の画像を画面の左下から右下に移動します。月が動くにつれて、クレジットのテキストがalpha="0.0"
からalpha="1.0"
にフェードインします。 - アプリを実行して、[Step 3] を選択します。月をクリックすると、月が始点から終点まで直線的な経路(または直線)をたどることがわかります。
ステップ 2: パスのデバッグを有効にする
月の動きに円弧を追加する前に、MotionLayout
でパスのデバッグを有効にすると便利です。
MotionLayout
を使用して複雑なアニメーションを作成できるように、すべてのビューのアニメーション パスを描画できます。これは、アニメーションを可視化する場合や、動きの細かい部分を微調整する場合に役立ちます。
- パスのデバッグを有効にするには、
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" >
パスのデバッグを有効にしてアプリを再度実行すると、すべてのビューのパスが点線で視覚化されます。
- 円は、1 つのビューの開始位置または終了位置を表します。
- 線は 1 つのビューのパスを表します。
- ひし形はパスを変更する
KeyPosition
を表します。
たとえば、このアニメーションでは、中央の円がクレジット テキストの位置です。
ステップ 3: パスを変更する
MotionLayout
のすべてのアニメーションは、開始と終了によってConstraintSet
定義され、アニメーションの開始前と終了後の画面の外観を定義します。デフォルトでは、MotionLayout
は位置が変わる各ビューの開始位置と終了位置の間に直線パス(直線)をプロットします。
この例の月の弧のような複雑な経路を作成するために、MotionLayout
は KeyPosition
を使用して、ビューが始点と終点の間に通る経路を変更します。
xml/step3.xml
を開き、KeyPosition
をシーンに追加します。KeyPosition
タグはTransition
タグ内に配置します。
step3.xml
<!-- TODO: Add KeyFrameSet and KeyPosition -->
<KeyFrameSet>
<KeyPosition
motion:framePosition="50"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.5"
/>
</KeyFrameSet>
KeyFrameSet
は Transition
の子であり、遷移中に適用されるすべての KeyFrames
(KeyPosition
など)のセットです。
MotionLayout
は、月の始点から終点までの経路を計算するため、KeyFrameSet
で指定された KeyPosition
に基づいて経路を変更します。アプリを再度実行すると、これによってパスがどのように変更されるかを確認できます。
KeyPosition
には、パスの変更方法を示す属性がいくつかあります。最も重要なものは次のとおりです。
framePosition
は 0 ~ 100 の数値です。これは、アニメーション内でこのKeyPosition
を適用するタイミングを定義します。1 はアニメーション全体の 1%、99 は 99% です。値が 50 の場合は、中央から直接適用します。motionTarget
は、このKeyPosition
がパスを変更するビューです。keyPositionType
は、このKeyPosition
がパスを変更する方法を示します。次のステップで説明するように、parentRelative
、pathRelative
、deltaRelative
のいずれかを指定できます。percentX | percentY
は、framePosition
でパスを変更する度合いです(0.0 ~ 1.0 の値、負の値と 1 より大きい値を指定できます)。
次のように考えることができます。「framePosition
で、keyPositionType
によって決定される座標に従って、percentX
または percentY
だけ移動することにより、motionTarget
のパスを変更します。」
デフォルトでは、MotionLayout
はパスの変更によって導入された角を丸くします。作成したアニメーションを見ると、曲がり角で月が曲がっていることがわかります。ほとんどのアニメーションでは、これで十分です。そうでない場合は、curveFit
属性を指定してカスタマイズできます。
実際に試す
アプリを再度実行すると、このステップのアニメーションが表示されます。
月は Transition
で指定された KeyPosition
を通るため、円弧に沿ったことになります。
<KeyPosition
motion:framePosition="50"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.5"
/>
この KeyPosition
は、「framePosition 50
(アニメーションの途中で)で、parentRelative
によって決定される座標(MotionLayout
全体)に従って 50% Y
(画面の半分)に 50% Y
だけ移動することで、motionTarget
@id/moon
のパスを変更します。」と読み取れます。
そのため、アニメーションの半分で、月は画面上で 50% 下がった KeyPosition
を通過する必要があります。この KeyPosition
は X の動きをまったく変更しないため、月は開始から終わりまで水平方向に動きます。MotionLayout
は、開始と終了の間を移動する際に、この KeyPosition
を通過する滑らかな経路を特定します。
よく見ると、クレジットのテキストは月の位置によって制約されています。なぜ垂直方向にも動かないのですか?
<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 について
前のステップでは、keyPosition
タイプの parentRelative
を使用して、パスを画面の 50% だけオフセットしました。属性 keyPositionType
は、MotionLayout が percentX
または percentY
に従ってパスをどのように変更するかを決定します。
<KeyFrameSet>
<KeyPosition
motion:framePosition="50"
motion:motionTarget="@id/moon"
motion:keyPositionType="parentRelative"
motion:percentY="0.5"
/>
</KeyFrameSet>
keyPosition
には、parentRelative
、pathRelative
、deltaRelative
の 3 種類があります。タイプを指定すると、percentX
と percentY
の計算に使用される座標系が変更されます。
座標系とは
座標系は、空間内の点を指定する手段です。画面上の位置を説明するのにも役立ちます。
MotionLayout
座標系はデカルト座標系です。つまり、X 軸と Y 軸は 2 本の垂直線で定義されます。この 2 つの主な違いは、画面上の X 軸の位置です(Y 軸は常に X 軸と垂直です)。
MotionLayout
のすべての座標系では、X 軸と Y 軸の両方で 0.0
~1.0
の範囲の値が使用されます。負の値と 1.0
より大きい値を許可できます。たとえば、percentX
の値が -2.0
の場合、X 軸と逆方向に 2 回進むことを意味します。
Algebra のクラスに似すぎているという方は、下の写真を見てください。
parentRelative 座標
parentRelative
の keyPositionType
は、画面と同じ座標系を使用します。MotionLayout
全体の左上に (0, 0)
を定義し、右下に (1, 1)
を定義します。
この例の月の弧のように、MotionLayout
全体を移動するアニメーションを作成する場合は、parentRelative
を使用できます。
ただし、パスを少し曲げるなど、動きに合わせて相対的にパスを変更する場合は、他の 2 つの座標系のほうが適しています。
deltaRelative 座標
デルタは変化を表す数学用語であるため、deltaRelative
は「相対変化」を意味します。deltaRelative
座標では、(0,0)
はビューの開始位置、(1,1)
は終了位置です。X 軸と Y 軸は画面と平行になっています。
X 軸は常に画面の水平、Y 軸は常に画面の垂直です。parentRelative
との主な違いは、座標はビューが移動する画面の部分のみを示す点です。
deltaRelative
は、水平方向と垂直方向の動きを個別に制御する場合に適した座標系です。たとえば、垂直方向(Y)の動きが 50% になった時点で完了し、水平方向(X)でアニメーションを続けるようなアニメーションを作成できます。
pathRelative 座標
MotionLayout
の最後の座標系は pathRelative
です。他の 2 つとは大きく異なり、X 軸は開始から終了までモーションパスをたどります。したがって、(0,0)
が開始位置、(1,0)
が終了位置です。
この方法が必要な理由一見すると意外に思えますが、この座標系は画面の座標系に合わせられていません。
pathRelative
はいくつかの点で非常に役立つことがわかりました。
- アニメーションの一部でビューの速度を上げる、遅くする、または停止する。X ディメンションは常にビューが通るパスと完全に一致するため、
pathRelative
KeyPosition
を使用して、そのパスの特定ポイントに到達するframePosition
を変更できます。そのため、framePosition="50"
でKeyPosition
をpercentX="0.1"
に設定すると、アニメーションが最初の 10% の動きに移動するのにかかる時間が 50% になります。 - パスに微妙な円弧を追加します。Y 次元は常に運動に対して垂直であるため、Y を変更すると、曲線までの経路も運動全体に対して相対的に変化します。
deltaRelative
が機能しない場合に、2 つ目のディメンションを追加。完全な水平方向と垂直方向のモーションの場合、deltaRelative
は有効なディメンションを 1 つだけ作成します。ただし、pathRelative
では常に使用可能な X 座標と Y 座標が作成されます。
次のステップでは、複数の KeyPosition
を使用して、さらに複雑なパスを作成する方法を学習します。
7. 複雑なパスの作成
前のステップで作成したアニメーションを見ると、滑らかな曲線になっていますが、より「月のような」形状にすることもできます。
複数の KeyPosition 要素を使用してパスを変更する
MotionLayout
は、動きを取得するために必要な数の KeyPosition
を定義することで、パスをさらに変更できます。このアニメーションでは円弧を作成しますが、画面の中央で月を上下に動かすこともできます。
xml/step4.xml
を開きます。先ほどと同じビューと、前のステップで追加したKeyFrame
が表示されます。- 曲線の頂点を丸めるには、
@id/moon
のパスにさらに 2 つのKeyPositions
(頂点に達する直前と後に 1 つずつ)を追加します。
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
を通過するスムーズな動きを作成する方法を示します。
実際に試す
- アプリを再度実行すると、ステップ 4 に進み、アニメーションの動作を確認します。月をクリックすると、開始から終了までの経路をたどり、
KeyFrameSet
で指定された各KeyPosition
を通過します。
自分だけで見る
他のタイプの KeyFrame
に進む前に、KeyFrameSet
にさらに KeyPositions
を追加して、KeyPosition
だけでどのような効果を作成できるか試してみましょう。
次の例は、アニメーション中に前後に動く複雑なパスを作成する方法を示したものです。
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. 動作中に属性を変更する
ダイナミック アニメーションの構築は、多くの場合、アニメーションの進行に合わせてビューの size
、rotation
、または alpha
を変更することを意味します。MotionLayout
では、KeyAttribute
を使用して、任意のビューの多くの属性をアニメーション化できます。
このステップでは、KeyAttribute
を使用して月の目盛りを作成し、回転させます。また、KeyAttribute
を使用して、月の移動がほぼ完了するまでテキストの表示を遅らせます。
ステップ 1: KeyAttribute を使用してサイズ変更と回転を行う
- 前のステップで作成したのと同じアニメーションを含む
xml/step5.xml
を開きます。多様性を高めるため、この画面では背景として別の宇宙の写真が使用されます。 - 月のサイズを大きくして回転させるには、
KeyFrameSet
のkeyFrame="50"
とkeyFrame="100"
に 2 つのKeyAttribute
タグを追加します。
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
は円弧の上部で発生し、ビューのサイズが 2 倍になり、-360 度(つまり 1 つの完全な円)が回転します。2 番目の KeyAttribute
は、2 番目の回転を -720 度(2 つの完全な円)まで終了し、scaleX
と scaleY
の値のデフォルトが 1.0 であるため、サイズを標準に戻します。
KeyPosition
と同様に、KeyAttribute
は framePosition
と motionTarget
を使用して、KeyFrame
を適用するタイミングと変更するビューを指定します。MotionLayout
は KeyPositions
の間を補間して、滑らかなアニメーションを作成します。
KeyAttributes
は、すべてのビューに適用できる属性をサポートしています。visibility
、alpha
、elevation
などの基本属性の変更をサポートしています。また、ここでやっているように回転を変更することや、rotateX
と rotateY
を使用して 3 次元で回転させたり、scaleX
と scaleY
でサイズを調整したり、ビューの位置を X、Y、Z で変換したりすることもできます。
ステップ 2: クレジットの表示を遅らせる
このステップの目標の一つは、アニメーションを更新して、アニメーションがほぼ完成するまでクレジット テキストが表示されないようにすることです。
- クレジットの表示を遅らせるには、
alpha
がkeyPosition="85"
まで 0 のままになるように、KeyAttribute
をもう 1 つ定義します。MotionLayout
は、引き続き 0 から 100 のアルファへスムーズに遷移しますが、アニメーションの最後の 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% で @id/credits
の alpha
が 0.0 に維持されます。アルファが 0 から始まるため、アニメーションの最初の 85% は非表示になります。
この KeyAttribute
の最終的な効果は、クレジットがアニメーションの最後に表示されることです。月が画面の右上隅に落ち着くのに合わせて、アイコンが調整されているように見えます。
あるビューのアニメーションを遅らせて、別のビューがこのように動くようにすることで、ユーザーにとって動的でインパクトのあるアニメーションを作成できます。
実際に試す
- アプリを再度実行し、ステップ 5 に進んでアニメーションの動作を確認します。月をクリックすると、
KeyFrameSet
で指定された各KeyAttribute
を通過して、開始から終了までの経路をたどります。
月を 2 つの完全な円を回転させるため、二重バックフリップします。クレジットにより、アニメーションがほぼ完成するまで、表示が遅延します。
自分で調べる
KeyFrame
の最終タイプに進む前に、KeyAttributes
の他の標準属性を変更してみてください。たとえば、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
を使用すると、セッターを持つ任意の値を設定できます。たとえば、CustomAttribute
を使用して View に backgroundColor を設定できます。MotionLayout
は reflection を使用してセッターを見つけ、それを繰り返し呼び出してビューをアニメーション化します。
このステップでは、CustomAttribute
を使用して月に colorFilter
属性を設定し、次のようなアニメーションを作成します。
カスタム属性を定義する
- まず、前のステップで作成したのと同じアニメーションを含む
xml/step6.xml
を開きます。 - 月の色を変えるには、
keyFrame="0"
、keyFrame="50"
、keyFrame="100".
のKeyFrameSet
にCustomAttribute
を指定した 2 つのKeyAttribute
を追加します。
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
内に CustomAttribute
を追加します。CustomAttribute
は、KeyAttribute
で指定された framePosition
に適用されます。
CustomAttribute
内に、attributeName
と設定する 1 つの値を指定する必要があります。
motion:attributeName
は、このカスタム属性によって呼び出されるセッターの名前です。この例では、Drawable
のsetColorFilter
が呼び出されます。motion:custom*Value
は、名前に記載されている型のカスタム値です。この例では、カスタム値は指定された色です。
カスタム値の型は次のいずれかです。
- 色
- Integer
- 浮動小数点数
- 文字列
- ディメンション
- ブール値
この API を使用すると、MotionLayout
は任意のビューでセッターを提供するあらゆるものをアニメーション化できます。
実際に試す
- アプリを再度実行し、ステップ 6 に進んでアニメーションの動作を確認します。月をクリックすると、
KeyFrameSet
で指定された各KeyAttribute
を通過して、開始から終了までの経路をたどります。
KeyFrames
を追加すると、MotionLayout
は月の道を直線から複雑な曲線に変更し、アニメーションの途中で二重バックフリップ、サイズ変更、色の変化を追加します。
実際のアニメーションでは、複数のビューを同時にアニメーション化し、さまざまな経路と速度で動きを制御することがよくあります。ビューごとに異なる KeyFrame
を指定することで、MotionLayout
で複数のビューをアニメーション化するリッチなアニメーションを作成できます。
10. ドラッグ イベントと複雑なパス
このステップでは、複雑なパスで OnSwipe
を使用する方法について説明します。ここまでのところ、月のアニメーションは OnClick
リスナーによってトリガーされ、一定の時間実行されています。
OnSwipe
を使用して複雑なパスを持つアニメーションを制御するには、たとえば、前の数ステップで作成した月のアニメーションのように、OnSwipe
の仕組みを理解する必要があります。
ステップ 1: OnSwipe の動作を確認する
xml/step7.xml
を開き、既存のOnSwipe
宣言を見つけます。
step7.xml
<!-- Fix OnSwipe by changing touchAnchorSide →
<OnSwipe
motion:touchAnchorId="@id/moon"
motion:touchAnchorSide="bottom"
/>
- デバイスでアプリを実行し、ステップ 7 に進みます。円弧の軌跡に沿って月をドラッグして、スムーズなアニメーションを作成できるか試してみましょう。
このアニメーションを実行すると、見栄えが良くありません。月が円弧の頂点に達すると、月がジャンプし始めます。
バグを理解するには、ユーザーが円弧のすぐ下の部分に触れた場合にどうなるかを検討します。OnSwipe
タグには motion:touchAnchorSide="bottom"
があるため、MotionLayout
はアニメーション全体で指とビューの底部の距離を一定にしようとします。
しかし、月の底は必ずしも同じ方向とは限らず、上がってから下がっていくため、ユーザーが円弧の頂点を過ぎたばかりの場合、MotionLayout
はどうすればよいかわかりません。これを考慮すると、ここでは月の底を追跡しているので、ユーザーがここに触れているときに月の底面をどこに置くべきでしょうか。
ステップ 2: 右側面を使用する
このようなバグを回避するには、アニメーション全体を通じて常に一方向に進行する touchAnchorId
と touchAnchorSide
を選択することが重要です。
このアニメーションでは、月の right
側と left
側の両方が画面を一方向に進めます。
ただし、bottom
と top
はどちらも逆方向になります。OnSwipe
が追跡しようとすると、方向が変わると混乱してしまいます。
- このアニメーションをタッチイベントに追随させるには、
touchAnchorSide
をright
に変更します。
step7.xml
<!-- Fix OnSwipe by changing touchAnchorSide →
<OnSwipe
motion:touchAnchorId="@id/moon"
motion:touchAnchorSide="right"
/>
ステップ 3: dragDirection を使用する
dragDirection
を touchAnchorSide
と組み合わせて、サイドトラックを通常とは異なる方向に作成することもできます。touchAnchorSide
が一方向にしか進まないことは重要ですが、トラッキングする方向を MotionLayout
に指示することは可能です。たとえば、touchAnchorSide="bottom"
を残して dragDirection="dragRight"
を追加できます。これにより、MotionLayout
はビューの底部の位置を追跡しますが、右に移動する場合にのみ位置を考慮します(垂直方向の動きは無視されます)。そのため、下部が上下しても、OnSwipe
で正しくアニメーション化されます。
- 月の動きを正しく追跡できるように、
OnSwipe
を更新します。
step7.xml
<!-- Using dragDirection to control the direction of drag tracking →
<OnSwipe
motion:touchAnchorId="@id/moon"
motion:touchAnchorSide="bottom"
motion:dragDirection="dragRight"
/>
実際に試す
- アプリを再度実行し、パス全体を通して月をドラッグしてみてください。
MotionLayout
は複雑な円弧に沿っていますが、スワイプ イベントに応じてアニメーションを進めることができます。
11. コードを使ったランニング モーション
MotionLayout
を CoordinatorLayout
と併用すると、リッチなアニメーションを作成できます。このステップでは、MotionLayout
を使用して折りたたみ可能なヘッダーを作成します。
ステップ 1: 既存のコードを確認する
- まず、
layout/activity_step8.xml
を開きます。 layout/activity_step8.xml
では、動作中のCoordinatorLayout
とAppBarLayout
がすでにビルドされています。
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>
このレイアウトでは、CoordinatorLayout
を使用して、NestedScrollView
と AppBarLayout
の間でスクロール情報を共有します。そのため、NestedScrollView
が上にスクロールすると、AppBarLayout
に変更が通知されます。このように折りたたみツールバーを Android に実装すると、テキストのスクロールが「調整」されます。折りたたみヘッダーを使用します。
@id/motion_layout
が指すモーションシーンは、最後のステップのモーションシーンに似ています。ただし、CoordinatorLayout
で機能させるために OnSwipe
宣言が削除されました。
- アプリを実行して、ステップ 8 に進みます。テキストをスクロールしても月が動かないことがわかります。
ステップ 2: MotionLayout をスクロールさせる
NestedScrollView
がスクロールされるとすぐにMotionLayout
ビューをスクロールするには、motion:minHeight
とmotion:layout_scrollFlags
をMotionLayout
に追加します。
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" >
- アプリを再度実行し、ステップ 8 に進みます。上にスクロールすると、
MotionLayout
が折りたたまれます。ただし、スクロール動作に基づいてアニメーションはまだ進行しません。
ステップ 3: コードを使用してモーションを移動する
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
は、progress プロパティを設定することで遷移のシークをサポートします。verticalOffset
と進行状況の割合を変換するには、スクロール範囲の合計で割ります。
実際に試す
- アプリを再度デプロイし、ステップ 8 のアニメーションを実行します。
MotionLayout
がスクロール位置に基づいてアニメーションを進めていることがわかります。
MotionLayout
を使用して、カスタムの動的な折りたたみツールバー アニメーションを作成できます。KeyFrames
のシーケンスを使用することで、大胆な効果を実現できます。
12. 完了
この Codelab では、MotionLayout
の基本 API について説明しました。
MotionLayout
の実際の使用例については、公式のサンプルをご覧ください。また、必ずドキュメントをご確認ください。
詳細
MotionLayout
は、この Codelab で扱っていないその他の機能をサポートしています。たとえば、繰り返しサイクルでパスや属性を制御できる KeyCycle,
や、時刻に基づいてアニメーション化できる KeyTimeCycle,
などです。それぞれの例については、サンプルをご覧ください。
このコースの他の Codelab へのリンクについては、Kotlin を使用した高度な Android Codelab のランディング ページをご覧ください。