MotionLayoutはConstraintLayoutを継承し、レイアウト内の要素の動きの軌跡とアニメーションを管理するために使用されます。API 14との下位互換性があります。
MotionLayoutは、レイアウトの遷移や複雑な動きを簡単にすることができ、、、 様々な機能を提供します。
まずは簡単なエフェクトで試してみましょう。
MotionLayoutレイアウトには2つの部分があり、1つは通常のxmlファイルであり、もう1つはディレクトリres/xml/フォルダに対応するファイルのアニメーションシーンを記述するために使用されるxmlファイルに対応し、次のシーンアニメーションファイルと呼ばれています。
MotionLayoutActivityという名前の新しいアクティビティを作成し、この時間は、システムが良いデフォルトのレイアウトファイル、ConstraintLayoutのルートレイアウトを作成している、AndoridStudioはすぐにファイルの下にres/xmlフォルダを作成することができます、次のグラフは、レイアウトファイルは、フルプレビューに切り替えます。インターフェイスに切り替え、ConstraintLayoutを見つけ、右クリックしてMotionLayoutに変換を選択すると、resディレクトリの下にxmlディレクトリと現在のレイアウトに対応するシーンアニメーションxmlファイルが作成されていることがわかります。
app:layoutDescription
まず、レイアウトファイルにImageViewを追加し、レイアウト内のMotionLayoutが、レイアウトによって参照されるシーンアニメーションファイルを参照します。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://..com/apk/res/android"
xmlns:app="http://..com/apk/res-auto"
xmlns:tools="http://..com/tools"
android:id="@+id/iv_3"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/activity_motion_layout_scene"
tools:context=".ui.motionlayout.MotionLayoutActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="50dp"
android:layout_height="50dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@drawable/expression_3"
tools:layout_editor_absoluteY="74dp" />
</androidx.constraintlayout.motion.widget.MotionLayout>
次に、シーンアニメーションファイルにアニメーションを追加します
<?xml version="1.0" encoding="utf-8"?>
<MotionScene
xmlns:android="http://..com/apk/res/android"
xmlns:motion="http://..com/apk/res-auto">
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<KeyFrameSet>
</KeyFrameSet>
<OnClick motion:targetId="@id/imageView" />
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint
android:layout_height="50dp"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
android:layout_width="50dp"
android:id="@+id/imageView"
motion:layout_constraintHorizontal_bias="0.052"
motion:layout_constraintBottom_toBottomOf="parent"
android:rotation="0"
/>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:layout_height="50dp"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
android:layout_width="50dp"
android:id="@+id/imageView"
motion:layout_constraintHorizontal_bias="0.915"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintTop_toTopOf="parent"
motion:layout_editor_absoluteY="43dp"
android:rotation="360" />
</ConstraintSet>
</MotionScene>
すると、ImageViewが画面の左側から右側へスライドするシンプルなアニメーションができます。エフェクトは次のようになります
注:MotionLayoutアニメーションの編集のためのAndoridStudio4.0は非常に強力である後、エディタを介してAndroidStudioでは、すぐにアニメーションを完了することができ、自動的に上記のコードを生成するので、時にはエディタとコードを組み合わせて使用されますすぐにドラッグして、一般的な実装をドロップするエディタと、高速になりますし、によって。コード変更の詳細
ここでは、これらのタグがシーン・アニメーション・ファイルで何を表しているかを簡単に説明し、その後に続く例で遊んでみましょう。以下のタグは、重要なプロパティのリストにすぎません。すべてのプロパティについては、クリックして属性アニメーション表示してください。
シーンアニメーションファイルのルート要素で、1つ以上の
<ConstraintSet>
タグは必須です。
これは、モーションシーケンスの開始状態と終了状態、中間状態、およびクリックやスライドなどのモーションのトリガー方法を指定します。
重要なプロパティです:
- motion:constraintSetStart: モーションシーケンスの初期状態。
<ConstraintSet>
これは、IDまたはレイアウトになります。<ConstraintSet>
指定するには、このプロパティを"@+id/constraintSetId "に設定します。レイアウトを指定するには、このプロパティに"@layout/layoutState "を設定します。 - motion:constraintSetEnd: モーションシーケンスの終了状態。
- motion:duration: モーションシーケンスの継続時間です。指定されていない場合は、
要素のデフォルトの継続時間が 使われます。 - motionInterpolator: インターポレーター効果は、属性アニメーションのインターポレーターと同じです。値は、linear、bounce spring、easeIn fade in、easeOut fade out、easeInOut fade in fade outです。
内部には3つのサブタブがあります
: はユーザーがクリックすることでアニメーションをトリガーすることを意味します。 は、ユーザーがスライドすることによってアニメーションをトリガーすることを意味します。 <KeyPosition/>
<KeyAttribute>
キーフレーム(KeyFrame)は、曲線の動きや折れ線の動きなど、アニメーションシーケンスの中間位置を扱うために使用されます。これらの2つの仲間の属性が多く、具体的な属性は、ドキュメントTransitionManager、CoordinatorLayout見ることができます。
このタグは、ページ上の状態のすべてのインタフェース要素の位置を指定するために使用され、一般的に2つの開始位置、終了位置、<ConstraintSet>
<ConstraintSet>
1つまたは複数の制約ラベルを含む必要があります制約ラベルのコレクションで
主なタグのいくつかは知っている意味OK、いくつかのアニメーションを行うには、これらのタグを使用しようとすると、次のとおりです。
これらのタグを使用して、アニメーションを実行してみましょう。 Viewの色遷移を設定するために、以下を見てみましょう。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://..com/apk/res/android"
xmlns:app="http://..com/apk/res-auto"
xmlns:tools="http://..com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/activity_motion_layout1_scene">
<View
android:id="@+id/btn_view"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginEnd="411dp"
android:layout_marginBottom="731dp"
android:background="@color/colorAccent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.motion.widget.MotionLayout>
シーンアニメーションファイル
<?xml version="1.0" encoding="utf-8"?>
<MotionScene
xmlns:android="http://..com/apk/res/android"
xmlns:motion="http://..com/apk/res-auto">
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<KeyFrameSet>
</KeyFrameSet>
<OnSwipe
motion:touchAnchorId="@id/btn_view"
motion:dragDirection="dragRight"
motion:touchAnchorSide="right"
/>
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint
android:layout_width="50dp"
android:layout_height="50dp"
motion:layout_constraintTop_toTopOf="parent"
android:id="@+id/btn_view"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintLeft_toLeftOf="parent"
>
<CustomAttribute
motion:attributeName="BackgroundColor"
motion:customColorValue="@color/colorPrimary" />
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:layout_width="50dp"
android:layout_height="50dp"
motion:layout_constraintTop_toTopOf="parent"
android:id="@+id/btn_view"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintRight_toRightOf="parent" >
<CustomAttribute
motion:attributeName="BackgroundColor"
motion:customColorValue="@color/colorAccent" />
</Constraint>
</ConstraintSet>
</MotionScene>
motion:touchAnchorId
motion:dragDirection
motion:touchAnchorSide
今回は、指がスライドしたときにアニメーションを起動するタグを使います。この例では、アニメーションが制御するViewのidを表し、指が右にスライドすることを表し、最終的に右側で停止することを表しています。
次のアニメーションを見て、ImageViewをY軸に沿って60度回転させ、これは非常に簡単ですが、rotationY属性の追加に基づいて、最初のアニメーションですることができ、状態の開始時にrotationY属性が0に設定され、状態の終了rotationY属性は、それの実現に60に設定されます。
次へ
次へ
このエフェクトは前のものと似ていますが、実装方法が異なります。 前のものはpathMotionArcプロパティによって実装されていますが、値がいくつかしかなく、カスタマイズすることができません。
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<KeyFrameSet>
<KeyPosition
motion:motionTarget="@+id/imageView"
motion:framePosition="46"
motion:keyPositionType="pathRelative"
motion:percentY="0.255" />
</KeyFrameSet>
<OnClick motion:targetId="@id/imageView" />
</Transition>
このモーション曲線の曲率は、percentYプロパティの値を調整することで調整できます。
次へ
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<KeyFrameSet>
<KeyPosition />
<KeyCycle
motion:motionTarget="@+id/imageView"
motion:framePosition="99"
motion:wavePeriod="1"
android:translationX="70dp"
motion:waveShape="sin" />
</KeyFrameSet>
<OnClick motion:targetId="@id/imageView" />
</Transition>
- framePosition: 1から99までの整数で、モーションシーケンス内でビューが指定されたプロパティを持つタイミングを指定するために使用します。
- wavePeriod: この領域でビューが振動する回数で、値が大きいほど振動が速くなります。
- translationX:ビューが振動するX軸上の距離。
次へ
このgif記録の問題は、実際の効果がImageViewが急速に3600度回転することです!
これは非常に簡単で、android:rotation="3600 "属性を追加した終了位置で、開始位置と終了位置は変更されず、この効果を達成することができます。
この目的は、xmlでこのアニメーションを実装できるだけでなく、コード内でアニメーションのプロパティを動的に変更できることを説明することです。
val constraintSet = motionlayout.getConstraintSet(R.id.end)
constraintSet.setRotation(R.id.imageView,7200f)
motionlayout.updateState(R.id.end,constraintSet)
idでConstraintSetを取得し、そのプロパティを変更し、最終的に3600度を7200度に変更する上記のように状態を更新します。
次へ
一昔前は、このような効果を得るには、ViewGroupをカスタマイズし、様々な位置を計算し、アニメーションを実装する必要がありました。
layout_constraintCircle
layout_constraintCircleRadius
layout_constraintCircleAngle
現在では、motionlayoutによって非常に素早く実現することができます。まず、メインのxmlファイルに5つのImageViewを追加し、シーンアニメーションのxmlファイルでは、すべてのImageViewに同じ開始位置を持たせ、終了位置で弧を描くように異なる位置に配置します。これは、ConstraintLayout自体でサポートされており、それぞれ配置される属性である , を使用します。例えば、次のコードの1つ
<Constraint
motion:layout_editor_absoluteY="651dp"
android:layout_height="50dp"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintCircle="@id/imageView"
motion:layout_constraintCircleRadius="180dp"
motion:layout_constraintCircleAngle="60"
motion:layout_constraintEnd_toEndOf="parent"
android:layout_width="50dp"
android:rotation="360"
android:id="@+id/imageView2" />
次へ
このアニメーションの実装は簡単で、IngeViewをクリックすると、そのIngeViewが中央の位置に移動し、X軸とY軸が2倍に拡大縮小されます。
異なるImageViewをクリックすると効果が異なるので、それぞれの状態に対応するように4つのTransitionと4つのConstraintSetを設定する必要があります。
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="500">
<OnClick motion:targetId="@id/imageView4" />
</Transition>
<Transition
android:id="@+id/action1"
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/end1"
motion:duration="500">
<OnClick motion:targetId="@id/imageView2" />
</Transition>
<Transition
android:id="@+id/action2"
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/end2"
motion:duration="500">
<OnClick motion:targetId="@id/imageView" />
</Transition>
<Transition
android:id="@+id/action3"
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/end3"
motion:duration="500">
<OnClick motion:targetId="@id/imageView3" />
</Transition>
MotionLayoutアニメーションは無限の想像力をもたらすことができ、唯一の公式デモは、次の公式デモ視差アニメーションのような達成するために多くのクールな効果を持っています。
マウスがクリックに敏感ではない場合、スライドViewPagerアニメーションも同期実行されます。
上がカスタムMotionLayout、真ん中がTabLayout、下がViewPagerです。
車、木、山の開始位置と終了位置を設定します。 カスタムMotionLayoutの目的は、ViewPagerのスライドイベントをリスニングし、スライドイベントで現在のアニメーションの進行状況を設定することです。
class ViewpagerHeader @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : MotionLayout(context, attrs, defStyleAttr), ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
val numPages = 3
progress = (position + positionOffset) / (numPages - 1)
}
override fun onPageSelected(position: Int) {
}
}
公式デモには興味深い実装がたくさんあるので、ダウンロードして実行すると 見ることができます 。
MotionLayoutは、いくつかの複雑でクールなアニメーションを実現するために非常に便利なことができ、デザイナーの妹は非常にクールなアニメーションをもたらすために、あなたが最初に達成するためにMotionLayoutの使用を考えることができる、すぐに多くの時間を節約するために完了することができるかもしれません。