Material Design motion system (Beta)とAndroidの実装 (Android Material Component 1.2.0-alpha05時点)
きっかけ
Android Material Component 1.2.0-alpha05がリリースされ、これが入ったので見てみました。
概要
このドキュメントによると、Material Design’s motion systemのUIのコンポーネントや画面の遷移のパターンは4つから構成されます。
https://material.io/design/motion/the-motion-system.html#transition-patterns
- Container transform
- Shared axis
- Fade through
- Fade
それぞれの説明と実装方法
基本的にはここにあるとおりですが、ちょっとかいつまんで説明します。
https://material.io/develop/android/theming/motion/#material-container-transform
Container transform
共通の要素がある場合の遷移、リストの一行と詳細画面が関連あるなどの場合。
例:
- DroidKaigiのアプリでいうとセッション一覧とセッション詳細。
- セッション詳細にあるスピーカーの情報とスピーカー詳細。
どんなアニメーション?
AndroidでいうとViewGroupなどコンテナになっている部分をSharedElementTransionするイメージ
実装方法
MaterialContainerTransformを利用します。MaterialContainerTransformはAndroidXではなくAndroidのプラットフォームにあるandroid.transition.Transitionを継承しています。
これまでは画像など単体のViewをShared Element Transitionとして共有していましたが、この方法ではViewGroupなどを共有します。
MaterialContainerTransformは具体的にどうやってレイアウトを描画するか?
MaterialContainerTransform.TransitionDrawableというのがMaterialContainerTransformの中にあり、そのcanvasに始まりと終わりのViewをdrawすることによって実現しているようです。結構コード読みやすいので、ハマったらコード読むと解決できます。
※ MaterialContainerTransform.TransitionDrawable内
Fragment AからFragment Bに遷移するときの基本的な実装方法
- 遷移元フラグメントFragment A
transitionNameを遷移元レイアウトにつけ、FragmentNavigatorExtrasで渡して(Navigationを使わないでやる場合は
.addSharedElement(view, “shared_element_container”)
といった感じでやるみたいです。)、Navigationのextraで渡してあげればOKです。
// 今まではImageViewなどにつけていたが、レイアウトにtransitionNameをつける
binding.root.transitionName =
"${speaker.id}-${SessionDetailFragment.TRANSITION_NAME_SUFFIX}"
binding.root.setOnClickListener {
// ViewとTransitionNameの関連付けをextraに入れる。
val extras = FragmentNavigatorExtras(
binding.root to binding.root.transitionName
)
binding.root.findNavController()
.navigate(
SessionDetailFragmentDirections.actionSessionToSpeaker(
speaker.id,
SessionDetailFragment.TRANSITION_NAME_SUFFIX,
null
),
// extraをNavigationで渡す
extras
)
}
- Fragment BのenterTransitionにMaterialContainerTransform()を入れる。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sharedElementEnterTransition = MaterialContainerTransform(requireContext())
- 行き先のルートViewなどに同じTransitionNameをつけてあげる。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val binding = FragmentSpeakerBinding.bind(view)
binding.speakerRoot.transitionName = "${navArgs.speakerId}-${navArgs.transitionNameSuffix}"
基本的にはMaterialContainerTransformを使うこと以外はレイアウトを指定したShared Element Transitionを実装すればOKです
プルリクで実装を見たければこちらで見られます。
https://github.com/DroidKaigi/conference-app-2020/pull/810/files
ハマりどころ(今回は詳しく書かないです)
- exit transitionがデフォルトでAndroidXのtransitionになっていて、enter transitionがプラットフォームのtransitionになるのでクラッシュする。両方プラットフォームかAndroidXのtransitionでなくてはならない。
- アニメーションする先が画面全体ではない場合(DroidKaigiアプリではToolbarがActivityにあった)、drawingViewIdを使って画面の裏がフェードする範囲を変える必要がある。
- Transition対象のViewにはbackgroundをつけておかないとうまく動かなかったりする。
MaterialContainerTransform.setDrawDebugEnabledを使うことでアニメーションのデバッグができます。
Shared axis
空間やナビゲーションなどで位置関係があるUI要素での切り替え。X Y Z軸でスライドさせるような形で利用でき、要素間の関係を強化できる。
例:
- チュートリアルで下にカルーセルがあって、押したときに横にスクロールされて切り替えるなど。並列の要素で位置関係があるもの。
MaterialSharedAxisというTransitionを利用します。
詳しくはドキュメントやこのあたりの実装を見ていくことで実装できそうです。
https://material.io/develop/android/theming/motion/#shared-axis
https://github.com/material-components/material-components-android/blob/8e8d20c94f3573f7f7418f3971fbbc41a4fa83bd/catalog/java/io/material/catalog/transition/TransitionSharedAxisDemoFragment.java#L101
Fade through
お互いに関係がないUI要素間での切り替えに利用します。BottomNavigationでの切り替えなどに利用します。
MaterialFadeThroughというTransitionを利用します。
詳しくはドキュメントやこのあたりの実装を見ていくことで実装できそうです。
https://material.io/develop/android/theming/motion/#shared-axis
https://github.com/material-components/material-components-android/blob/8e8d20c94f3573f7f7418f3971fbbc41a4fa83bd/catalog/java/io/material/catalog/transition/TransitionSharedAxisDemoFragment.java#L101
Fade
例えばFabが表示されたり、Dialogが表示されたり消えたりと言った。UI要素が表示されるときに利用するパターンのようです。
MaterialFadeというTransitionを利用します。
https://material.io/develop/android/theming/motion/#fade
https://github.com/material-components/material-components-android/blob/8e8d20c94f3573f7f7418f3971fbbc41a4fa83bd/catalog/java/io/material/catalog/transition/TransitionFadeDemoFragment.java#L62
まとめ
新しいMaterial Design motion systemではアニメーションの種類がかなり絞られて、また実装的にも簡単にできるように工夫されており、Transitionでハマって時間をめちゃくちゃ吸われるようなことが少なくなりました。
Jetpack Composeにも将来的には同じような仕組みが入るのかなと予想できますが待ってみましょう。
Author And Source
この問題について(Material Design motion system (Beta)とAndroidの実装 (Android Material Component 1.2.0-alpha05時点)), 我々は、より多くの情報をここで見つけました https://qiita.com/takahirom/items/09848c48e4854f30bc6e著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .