2019の16日目の記事です。AndroidのレイアウトとアニメーションをMotionLayoutで作ったら色々ハマりました、という記事です。前置きMotionLayout(が含まれるConstraintLayoutパッケージ)はまだBetaバージョンのため、今後の更新によって記事の内容が適用できなくなる可能性があります。ベースにして書かれています。「まだこれはできません」「こうするとバグります」などと書きますが、全てを複数の環境で確認したわけではないので、誤謬が含まれている可能性があります。「知らないだけでできる」「こっちでは動く」「おま環」などがあれば教えて下さい。UIの要素間に制約を設定することで画面レイアウトを作成するための仕組みです。こいつの詳しい説明は割愛いたします。(実装上もMotionLayoutはConstraintLayoutの子クラス)こちらは、一つの画面に対して複数のレイアウトを設定することができ、この複数のレイアウト間をアニメーションしながら切り替えることができる優れもの、なんですが、気をつけないといけない部分がとても多くなかなか苦労させられます。実例を交えて説明します。Map(iOS)のこのUIのように下からViewがせり上がってくるアニメーションを作ってみます。</ConstraintSet></MotionScene>で、画面を上下に擦るとこうなります割と簡単にリッチなアニメーションができましたね。軽く説明しておきます。)が追加されています。ここで指定したリソースにMotionLayoutを動かすために必要なMotionScene要素を記述します。付加していますが、どんな名前でも大丈夫です。制約が書いてありません。MotionLayoutで動かしたい要素は、motionファイルの方で制約を記述するので何も書かなくて良いです。逆に、MotionLayoutで動かさない要素は、ConstraintLayoutの方で制約を書いてあれば、motionファイルでは考慮しなくて良くなります。ファイルですが、MotionScene要素の中にTransition要素とConstraintSet要素が入っていることがわかります。ファイルと同じように制約を記述します。付かないものは大半消してしまっても構いません。要素はConstraintには必要ありません。アニメーションしながら色を徐々に変えたい、とかには使えません。Transitionは、どこからどこまで、どうアニメーションさせるかを記述します。囲ってもちゃんと動く。指定したConstraintのPreviewがちゃんと描画されていた。ファイルに二回(状態が増えればもっと)同じ記述をしなければならず地獄だった。(後述)によりかなり楽になったコードから動かしたい最低限動くところから、実際のアプリケーションではもっと様々な要求が生まれると思います。別のイベントによりアニメーションを実行させたいとします。Int)を呼び出せばOKです。setStateは壊れており、何をしてもうんともすんとも言いません。<任意のInt>)setTransitionを使う方法を採用していたのですが、何度か動かしているとConstraintが張り付いて全く動かなくなる現象が起きるので、あまりおすすめの方法とは言えません。アニメーションの時間を0にするのが良いと思います。0にする方法は書いていて気づきました。代わりに悪用するために存在するはずではないような気がするんですが、どうやって使うんですか?動的にアニメーションを設定できそうな気配は感じられるのですが、肝心のアニメーションを呼び出すメソッドは見当たらず・・・と思っていたんですが、progressに値をセットしたいときにどのアニメーションのprogressかを指定できるっぽいですね。この記事書いてよかった~複数の状態の間をアニメーションしたい実際のアニメーションでは、一つのViewが展開して閉じるだけではありません。展開の途中で止めてちいさなUIとして表示しておきたい、という要望があるかもしれません。他のViewが全く別のタイミングでアニメーションする場合は?こういう場合、ConstraintSetは2つでは足りません。記述することはある程度考慮されているため、上の例にならって、どんどん増やしてしまって構いません。Viewの要素が多くなってくると、全てのConstraintSetで同じような記述をすることに飽きてきて「ここの状態間では動くけど、他の状態では常に同じ位置にいるので何度も書きたくない」、という要望が発生すると思います。Constraintsを利用しましょう。したConstraintSetを参照してくれます。特定の条件でしか使えませんが、記述量を減らす記法として、XMLの属性ではなく子要素として書く記法が使えることがあります。して記述することができます。</Constraint></ConstraintSet>このようにLayout関連の記述をすっ飛ばすことができます。残念ながら、制約のうち一部だけ変更したいので全部は書きたくない、といった要望には適しませんが、Layoutは変わらないがMotionLayoutで制御できる一部の属性のみ変更したい、といった状況はあり得ると思うので、覚えておいて損はないと思います。複数状態をMotionLayoutで制御しようとすると、一つの(現状どうしようもない)問題が発生します。それは、MotionSceneにはTransitionは一つしか設定できない、ということです。各状態間のアニメーションごとに、OnClickやOnSwipeを設定する事はできず、手軽にリッチなアニメーションが実装できる、という利点が少々薄れてしまいます。設定すれば起きない)ので、意味はなくともつけておいたほうが無難ですアニメーションの終了等のイベントが取りたいListenerの登録ができます。})これでOK、なんですが、ここで流れてくるIdでハマることがあります。いう要素を追加できます。これは何かというと、ConstraintSetとStateを対応付けて管理したり、defaultStateを設定したりできるもの、のハズなんですが、今の所あんまり機能していません。defaultStateですが、これを設定することで最初に画面に表示されるConstraintSetを変更できる、ように思えます。最初に画面に表示されるConstraintSetの優先順位は、以下のようになっています。若いidをもつConstraintSetdefaultStateは特に関係ありません。なんのために存在する属性なんでしょうか。これにはミュウツーもニッコリです。