fresh digitable

めんどくさかったなってことを振り返ったり振り返らなかったりするための記録

NavigationとMaterialContainerTransformを使う

github.com

なんかいろいろあったのでメモ。

今回の前提

implementation "androidx.navigation:navigation-fragment-ktx:2.3.0-alpha06"
implementation "androidx.navigation:navigation-ui-ktx:2.3.0-alpha06"
implementation "com.google.android.material:material:1.2.0-alpha06"

今回はListからDetailに遷移するときにContainer transformを入れてみることにした。ドキュメントに沿ってMaterialContainerTransformクラスを使って実装すれば大体のところまではできる。

material.io

material.io

引っかかったいくつかのところについてまとめておく。

遷移するときにListとDetailの表示が重なってしまう

Detail(上側)のViewがそれっぽく動いているのは見えるんだけどList(下側)も見えてしまうという感じ。背景の色を指定してやればよい。MDC初心者だったのでいっぱい調べました。

containerColor = Color.WHITE

ListからDetailはアニメーションするけど逆のときはしない

ドキュメントにはList -> Detailの実装のことしか書いていないし、これで逆向きのアニメーションもOKというようなこともそれとなく書いてある。実際にはそうなんだけど、Navigationコンポーネントと一緒に使うときには気を付けなければならない。issueにも挙がっているし一つ目のコメントに答えが書いてある。ざっくりいうと、Navigationコンポーネントで画面遷移するときに実行されるFragmentTransaction.setReorderingAllowed(true)が原因らしい。

[MaterialTransformContainer/Motion] sharedElementReturnTransition not working with navigation component · Issue #1073 · material-components/material-components-android · GitHub

setReorderingAllowed(true)は普通のshared elementアニメーションだと必要(参考: Android Developers Blog: Continuous Shared Element Transitions: RecyclerView to ViewPager )らしいのだけど、MaterialContainerTransformでは今のところ逆にうまくいかないらしい。ワークアラウンドについては次のissueが詳しい。

Navigation component: shared transitions backward not works · Issue #495 · android/architecture-components-samples · GitHub

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    postponeEnterTransition()
    view.doOnPreDraw { startPostponedEnterTransition() }
    ...
}

リストの一番上のアイテムだけDetailが半分になってしまう

それっぽく動いているように見えるが、

先頭のアイテムだけアニメーションがおかしい。

横から入ってきているように見えるが、実際にはアニメーションの最中だけViewが左側にずれてしまっている。モーションパスの始点と終点が同じだと動画のようになってしまうようす。苦し紛れにモーションパスを作るPathMotionクラスを実装して渡したら何となく動いたので、今のところのワークアラウンドとしておく。

https://github.com/akihito104/nasnen/pull/1/files#diff-cbd23c4e8d257b7f5cff6fa3da5bcdf9R42-R51

こういう使い方は想定していないのだろうか。例を見るとDetail側にはToolbarもContainerの中に入っているので、ここで見たような不具合は起きなさそうではある。