blog

Jetpack MotionLayout

から継承され、モーショントラックとアニメーションの要素のレイアウトを管理するために使用されます。API 14との下位互換性があります。 プロパティアニメーションを提供するために、よりシンプルな変換と...

Oct 5, 2020 · 12 min. read
シェア

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>タグは必須です。

ラベルには、defaultDuration 属性があり、遷移時間が設定されていない場合、すべての子要素のデフォルトの遷移時間をミリ秒単位で設定します。

これは、モーションシーケンスの開始状態と終了状態、中間状態、およびクリックやスライドなどのモーションのトリガー方法を指定します。

重要なプロパティです:

  • 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つの仲間の属性が多く、具体的な属性は、ドキュメントTransitionManagerCoordinatorLayout見ることができます。

このタグは、ページ上の状態のすべてのインタフェース要素の位置を指定するために使用され、一般的に2つの開始位置、終了位置、ラベルのconstraintSetEndとconstraintSetStart属性を介してidは、カスタムの定義に参照します<ConstraintSet>

<ConstraintSet>1つまたは複数の制約ラベルを含む必要があります制約ラベルのコレクションであり、コントロール内のメインレイアウトファイルと制約ラベルは、ImageViewのメインレイアウトなど、idを介して1対1の対応、対応するラベルのこちら側であり、その後、下のラベルにImageView属性の位置を制御します。

主なタグのいくつかは知っている意味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:touchAnchorIdmotion:dragDirectionmotion:touchAnchorSide今回は、指がスライドしたときにアニメーションを起動するタグを使います。この例では、アニメーションが制御するViewのidを表し、指が右にスライドすることを表し、最終的に右側で停止することを表しています。

次のアニメーションを見て、ImageViewをY軸に沿って60度回転させ、これは非常に簡単ですが、rotationY属性の追加に基づいて、最初のアニメーションですることができ、状態の開始時にrotationY属性が0に設定され、状態の終了rotationY属性は、それの実現に60に設定されます。

次へ

このアニメーションの実装はとても簡単で、まずImageViewの開始位置と終了位置を設定し、pathMotionArc属性のタグを使用します。属性の値は、属性の完了時にstartVerticalに設定されます!練習してみてください。

次へ

このエフェクトは前のものと似ていますが、実装方法が異なります。 前のものは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プロパティの値を調整することで調整できます。

次へ

このアニメーションでは、KeyCycleタグを使って

 <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_constraintCirclelayout_constraintCircleRadiuslayout_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" />

バウンス効果やフェードイン/フェードアウト効果を与えるために、タグにインターポレータ motionInterpolator を追加することもできます。

次へ

このアニメーションの実装は簡単で、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の使用を考えることができる、すぐに多くの時間を節約するために完了することができるかもしれません。

Read next

問題15 プロトタイプ・チェイニング

この図は少し複雑なので、私自身のバージョンを描きましたが、実際には上の図よりも1、2、3、4行多くなっています。 説明1.YES:__proto__の「インスタンス」の定義によると、aはbのインスタンス、つまりa bは真であり、デフォルトの判定条件はaのプロトタイプの連鎖にあることです。...

Oct 5, 2020 · 3 min read