CoordinatorLayout は、複雑なレイアウト、重複するレイアウト、ネストされたレイアウトを可能にする ViewGroup です。このクラスは、内部の View で、ツールバーやボトムシートの展開/折りたたみなど、特定のマテリアル デザインのインタラクションを有効にするコンテナとして使用されます。
Compose では、CoordinatorLayout に最も近いのは Scaffold です。Scaffold は、マテリアル コンポーネントを一般的な画面パターンやインタラクションに組み合わせるためのコンテンツ スロットを提供します。このページでは、CoordinatorLayout の実装を移行して Compose で Scaffold を使用する方法について説明します。
移行手順
CoordinatorLayout を Scaffold に移行する手順は次のとおりです。
次のスニペットでは、
CoordinatorLayoutにToolBar、ViewPager、FloatingActionButtonを含むAppBarLayoutが含まれています。UI 階層からCoordinatorLayoutとその子をコメントアウトし、それを置き換えるComposeViewを追加します。<!-- <androidx.coordinatorlayout.widget.CoordinatorLayout--> <!-- android:id="@+id/coordinator_layout"--> <!-- android:layout_width="match_parent"--> <!-- android:layout_height="match_parent"--> <!-- android:fitsSystemWindows="true">--> <!-- <androidx.compose.ui.platform.ComposeView--> <!-- android:id="@+id/compose_view"--> <!-- android:layout_width="match_parent"--> <!-- android:layout_height="match_parent"--> <!-- app:layout_behavior="@string/appbar_scrolling_view_behavior" />--> <!-- <com.google.android.material.appbar.AppBarLayout--> <!-- android:id="@+id/app_bar_layout"--> <!-- android:layout_width="match_parent"--> <!-- android:layout_height="wrap_content"--> <!-- android:fitsSystemWindows="true"--> <!-- android:theme="@style/Theme.Sunflower.AppBarOverlay">--> <!-- AppBarLayout contents here --> <!-- </com.google.android.material.appbar.AppBarLayout>--> <!-- </androidx.coordinatorlayout.widget.CoordinatorLayout>--> <androidx.compose.ui.platform.ComposeView android:id="@+id/compose_view" android:layout_width="match_parent" android:layout_height="match_parent" />フラグメントまたはアクティビティで、追加した
ComposeViewへの参照を取得し、そのsetContentメソッドを呼び出します。メソッドの本体で、Scaffoldをコンテンツとして設定します。composeView.setContent { Scaffold(Modifier.fillMaxSize()) { contentPadding -> // Scaffold contents // ... } }
Scaffoldのコンテンツ内に、画面のメイン コンテンツを追加します。上記の XML のメイン コンテンツはViewPager2であるため、Compose の同等のHorizontalPagerを使用します。Scaffoldのcontentラムダは、コンテンツ ルートに適用されるPaddingValuesのインスタンスも受け取ります。Modifier.paddingを使用して、同じPaddingValuesをHorizontalPagerに適用できます。composeView.setContent { Scaffold(Modifier.fillMaxSize()) { contentPadding -> val pagerState = rememberPagerState { 10 } HorizontalPager( state = pagerState, modifier = Modifier.padding(contentPadding) ) { /* Page contents */ } } }
Scaffoldが提供する他のコンテンツ スロットを使用して、画面要素を追加し、残りの子ビューを移行します。topBarスロットを使用してTopAppBarを追加し、floatingActionButtonスロットを使用してFloatingActionButtonを指定できます。composeView.setContent { Scaffold( Modifier.fillMaxSize(), topBar = { TopAppBar( title = { Text("My App") } ) }, floatingActionButton = { FloatingActionButton( onClick = { /* Handle click */ } ) { Icon( Icons.Filled.Add, contentDescription = "Add Button" ) } } ) { contentPadding -> val pagerState = rememberPagerState { 10 } HorizontalPager( state = pagerState, modifier = Modifier.padding(contentPadding) ) { /* Page contents */ } } }
一般的なユースケース
ツールバーを折りたたむ、展開する
View システムでは、CoordinatorLayout でツールバーを折りたたんだり展開したりするために、ツールバーのコンテナとして AppBarLayout を使用します。次に、関連付けられたスクロール可能な View(RecyclerView や NestedScrollView など)の XML で layout_behavior を介して Behavior を指定し、スクロール時にツールバーが折りたたまれたり展開されたりする動作を宣言します。
Compose では、TopAppBarScrollBehavior を使用して同様の効果を実現できます。たとえば、上にスクロールするとツールバーが表示されるように、折りたたみ/展開可能なツールバーを実装する手順は次のとおりです。
TopAppBarDefaults.enterAlwaysScrollBehavior()を呼び出してTopAppBarScrollBehaviorを作成します。- 作成した
TopAppBarScrollBehaviorをTopAppBarに指定します。 ScaffoldのModifier.nestedScrollを介してNestedScrollConnectionを接続し、スクロール可能なコンテンツが上下にスクロールしたときに Scaffold がネストされたスクロール イベントを受け取れるようにします。これにより、コンテンツのスクロールに合わせて、含まれているアプリバーが適切に折りたたまれたり展開されたりします。// 1. Create the TopAppBarScrollBehavior val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() Scaffold( topBar = { TopAppBar( title = { Text("My App") }, // 2. Provide scrollBehavior to TopAppBar scrollBehavior = scrollBehavior ) }, // 3. Connect the scrollBehavior.nestedScrollConnection to the Scaffold modifier = Modifier .fillMaxSize() .nestedScroll(scrollBehavior.nestedScrollConnection) ) { contentPadding -> /* Contents */ // ... }
折りたたみ/展開スクロール効果をカスタマイズする
enterAlwaysScrollBehavior に複数のパラメータを指定して、折りたたみ/展開のアニメーション効果をカスタマイズできます。TopAppBarDefaults は、コンテンツが一番下までスクロールされた場合にのみアプリバーを拡大する exitUntilCollapsedScrollBehavior などの他の TopAppBarScrollBehavior も提供します。
完全にカスタムのエフェクト(視差効果など)を作成するには、独自の NestedScrollConnection を作成し、コンテンツのスクロールに合わせてツールバーを手動でオフセットすることもできます。コード例については、AOSP のネストされたスクロールのサンプルをご覧ください。
ドロワー
Views では、DrawerLayout をルートビューとして使用して、ナビゲーション ドロワーを実装します。一方、CoordinatorLayout は DrawerLayout の子ビューです。DrawerLayout には、ドロワーにナビゲーション オプションを表示するための NavigationView などの別の子ビューも含まれています。
Compose では、ModalNavigationDrawer コンポーザブルを使用してナビゲーション ドロワーを実装できます。ModalNavigationDrawer は、ドロワー用の drawerContent スロットと、画面のコンテンツ用の content スロットを提供します。
ModalNavigationDrawer( drawerContent = { ModalDrawerSheet { Text("Drawer title", modifier = Modifier.padding(16.dp)) HorizontalDivider() NavigationDrawerItem( label = { Text(text = "Drawer Item") }, selected = false, onClick = { /*TODO*/ } ) // ...other drawer items } } ) { Scaffold(Modifier.fillMaxSize()) { contentPadding -> // Scaffold content // ... } }
詳しくは、ドロワーをご覧ください。
スナックバー
Scaffold は snackbarHost スロットを提供します。このスロットは、Snackbar を表示する SnackbarHost コンポーザブルを受け取ることができます。
val scope = rememberCoroutineScope() val snackbarHostState = remember { SnackbarHostState() } Scaffold( snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, floatingActionButton = { ExtendedFloatingActionButton( text = { Text("Show snackbar") }, icon = { Icon(Icons.Filled.Image, contentDescription = "") }, onClick = { scope.launch { snackbarHostState.showSnackbar("Snackbar") } } ) } ) { contentPadding -> // Screen content // ... }
詳しくは、スナックバーをご覧ください。
詳細
CoordinatorLayout を Compose に移行する方法について詳しくは、以下のリソースをご覧ください。
- マテリアル コンポーネントとレイアウト: Compose でサポートされているマテリアル デザイン コンポーネント(
Scaffoldなど)に関するドキュメント。 - Sunflower を Jetpack Compose に移行する:
CoordinatorLayoutを含む Sunflower サンプルアプリのビューから Compose への移行の過程を説明するブログ投稿。
あなたへのおすすめ
- 注: JavaScript がオフになっている場合はリンクテキストが表示されます
- マテリアル コンポーネントとレイアウト
- Compose でのウィンドウ インセット
- スクロール