言いたいことはそれだけか

KotlinとかAndroidとかが好きです。調べたことをメモします。٩( 'ω' )و

MotionLayoutの覚書き

はじめに

MotionLayoutが発表されて随分経った。「Android Studio 4系が必須でMotion Editorが来るのを待っていた」という言い訳で長い間スルーしていたが、そろそろ4系が安定して来たという話をちらほら聞くのでちょっとさわってみた。結果、Motion Editorなくても全然xml tag手書きでいけるということがわかったのでメモを残す。

ちなみにさわったのはこちらのcodelab。

codelabs.developers.google.com

MotionLayoutの基本

  • ConstraintLayoutを継承したMotionLayoutをparent viewとする
  • MotionLayoutのtag内にapp:layoutDescription="@xml/foo"といったようにMotionSceneを定義したxmlファイル名を指定する
  • MotionSceneにはTransitionConstraintSetを定義

Transition

  • Transitionのtag内にapp:constraintSetStart="@+id/start"みたいな感じでanimationのstart/endのConstraintSetを指定
  • Animationの契機となるOnClickOnSwipeなどはTransitionの中で定義する
  • animationのstart/endの間のPathを定義したい場合はTransitionの中でKeyFrameSetとその中にKeyPositionを定義する
  • KeyPosition
    • keyPositionTypeでどのようにMotionが変化するか指定する
    • 各typeについてはここを参照
      • parentRelativeはscreenと同じく左上が(0, 0)
  • animationのstart/endの間のview propertyを変えたい場合は KeyAttributeを定義する
    • KeyAttributeの中でCustomAttributeを設定することができる
    • CustomAttributeapp:attributeNameには対象クラスに定義されたsetter nameを指定する。(setXxxYyy()を使いたい場合はapp:attributeName="XxxYyy"になる。)

ConstraintSet

  • ConstraintSetの中ではanimationしたいviewごとにConstraintを定義
  • Constraintandroid:idには対象のviewを指定
  • layout fileに書いた各attributeはConstraintSetのxmlに定義したものに上書きされてしまう。 1そのため、android:layout_widthandroid:layout_heightを各Constraintで指定する必要がある。

覚えておきたい便利な機能・Tips

  • app:motionDebug="SHOW_PATH"MotionLayout のtagに入れることでmotionのpathをアプリ上で表示することができる
  • touchAnchorSideは基本的に一直線に進む方向を指定する必要がある(そうでないとanimationがおかしくなる場合がある)が、複雑なpathを書きたい場合はどの方向にも一直線に進まないケースがある。その場合はinvisibleなviewを一つ作ってそいつをanchorにするとうまくいく。
    • あるいはapp:dragDirectionを追加で指定することで解決するかもしれない
  • コードからmotionを動かしたいときはMotionLayout#setProgress(float pos)を使う
  • 既存のConstraintLayoutをMotionLayoutにconvertしたい場合は、下記手順で自動でconvertしてくれる
    1. layout xmlファイルを開く
    2. design serfaceを選択
    3. preview画面上で右クリック
    4. Convert to Motion Layout`を選択
  • ConstraintSetを使う時は全てのchildにidつけてやらないとDesign tabのpreviewもうまくrenderされない。またapp実行時に下記のRuntimeExceptionがthrowされる

    java.lang.RuntimeException: All children of ConstraintLayout must have ids to use ConstraintSet