Google I/O 2018で紹介されたMotionLayoutでできることとできないこと

Tsukamoto Takeshi
7 min readOct 6, 2018

--

Motion LayoutはConstraintLayout2.0.0から新たに追加されたViewで、Transitionの始点と終点における制約を指定するだけで宣言的にアニメーションを実装することができます。

公式のサンプルレポジトリに基本的なサンプルがまとまっているのでビルドしてみると大体何ができるかわかると思います。Fragmentに使えたり、ViewPagerと同期できたりとドキュメントだけではわからない便利な使い方が紹介されています。

※ConstraintLayout2.0.0-alpha2での注意

現在(2018/10/3)の最新バージョンであるConstraintLayout2.0.0-alpha2では下に上げる属性の動的な変更に対応していません。

alpha

visibility

elevation

rotationrotation[X/Y]

translation[X/ Y/Z]

scaleX/Y

これらの属性をkotlinやDatabindingなどを用いて動的に変更しているViewではMotionLayoutの導入が難しいです。

このバグは下のIssue Trackerに上がっていて2.0.0-alpha3で対応予定だとされているので、visibilityなどを動的に変更したい場合は次のバージョンまで待ったほうが良さそうです。

MotionLayoutでできること

始点と終点に別々のレイアウトを指定してアニメーションする

下のコードでこのようなアニメーションが作れます。

アニメーションを適用したいレイアウトファイル
MotionSceneの定義ファイル。res/xml下に置きます
アニメーションの始点用のレイアウトファイル
アニメーションの終点用のレイアウトファイル

元のレイアウトのlayoutDescriptionにMotionSceneを指定し、MotionSceneのTransitionのconstraintSetStartとconstraintSetEndに始点と終点のレイアウトに定義してアニメーションをすることができます。始点と終点で同一のIDのViewが別々のConstraintを持っている場合、アニメーションが補間されます。

始点と終点に別々のConstraintを指定してアニメーションする

上の方法では、アニメーションをさせるために、元々のレイアウトファイル、始点のレイアウトファイル、終点のレイアウトファイルと3つのほとんど同じレイアウトファイルが必要になります。これでは要素が増えるたびに3つのファイルを管理しなければならなくなります。constraintSetStartとconstraintSetEndはレイアウトファイルだけでなく、ConstraintSetも指定することができます。ConstraintSetを使えば上のコードを下のように書き換えられます。

こちらは元のレイアウトファイルとMotionSceneの定義だけで済むので、こちらの使い方を推奨します。

Constraint以外の属性を変更する

Viewの制約以外の属性もアニメーションに合わせて変更させることができます。Constantに下のようにCustomAttribeteを追加することで色の変化するアニメーションなども可能です。

アニメーションの任意の地点での属性を指定

KeyFrameSetを指定することで途中の値を変更できます。KeyFrameを指定しなかった場合、アニメーションの補間は始点と終点を繋いだ直線上で行われますが、KeyFrameSetを使うことでこの直線を曲げ流ことが出来ます。それ以外にも、「アニメーションが50%まで進行したときに色を青にする」のように細かい属性のコントロールが可能です。

MotionLayoutで出来ないこと

3つ以上のの状態をもつレイアウト

MotionLayoutで指定できるConstaraintSetは始点と終点に限られます。そのため3つ以上の状態をもつBottomSheetのような実装はできません。

相対値で変化するアニメーション

MotionLayoutは宣言的なアニメーションを実装するためのものなので、「60dp上にアニメーションする」といった相対値の指定はできません。

複数方向のドラッグにアニメーションを適用する

MotionSceneのTransition>OnSwipe属性をセットすることでスワイプを利用したアニメーションを定義できますが、OnSwipe属性は一つしか指定できないため、右にドラッグしたときのアニメーションと下にドラッグしたときのアニメーションを両方指定するといったことができません。

MotionLayoutの孫要素以下にアニメーションを適用する

MotionLayoutは子要素のみに影響します。そのためMotionLayout内にScrollViewなどを配置するとScrollView内の要素にはアニメーションを適用することが出来ません。同様に孫要素のドラッグやクリックに反応するアニメーションも定義できません。

MotionLayoutを使っていて、できなくて困ったことはこれくらいでした。何か解決方法があったら教えてください。

--

--