CoordinatorLayout を Compose に移行する

CoordinatorLayout は、複雑な重複するネストされたレイアウトを可能にする ViewGroup です。ツールバーやボトムシートの開閉など、特定のマテリアル デザインのインタラクションを内部のビューで可能にするためのコンテナとして使用されます。

Compose では、CoordinatorLayout に最も近い同等物は Scaffold です。Scaffold は、マテリアルを組み合わせるためのコンテンツ スロットを提供します。 コンポーネントを共通の画面パターンと操作に変換する。このページでは、以下の方法について説明します。 Scaffold を使用するように CoordinatorLayout の実装を移行できます。 作成。

移行手順

CoordinatorLayoutScaffold に移行する手順は次のとおりです。

  1. 次のスニペットでは、CoordinatorLayoutToolBarViewPagerFloatingActionButton を含む 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" />
    
  2. フラグメントまたはアクティビティで、追加した ComposeView への参照を取得し、その上で setContent メソッドを呼び出します。メソッドの本体で、コンテンツとして Scaffold を設定します。

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            // Scaffold contents
            // ...
        }
    }

  3. Scaffold のコンテンツで、画面のメイン コンテンツを できます。上記の XML の主なコンテンツは ViewPager2 であるため、 HorizontalPager: Compose でこれに相当します。Scaffoldcontent ラムダは、コンテンツ ルートに適用する PaddingValues のインスタンスも受け取ります。Modifier.padding を使用して、同じ PaddingValuesHorizontalPager に適用できます。

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

  4. Scaffold が提供する他のコンテンツ スロットを使用して、画面要素を追加し、残りの子ビューを移行します。topBar スロットを使用すると、 TopAppBarfloatingActionButton スロットを使用して、 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 をツールバーのコンテナとして使用します。次に、 関連するスクロール可能な要素に対する XML の Behaviorlayout_behavior ビュー(RecyclerViewNestedScrollView など)を使用してツールバーの スクロールすると折りたたみ/展開します。

Compose では、 TopAppBarScrollBehavior。たとえば、スクロールアップ時にツールバーが表示されるように、折りたたみ / 展開ツールバーを実装する手順は次のとおりです。

  1. TopAppBarDefaults.enterAlwaysScrollBehavior() を呼び出して TopAppBarScrollBehavior
  2. 作成した TopAppBarScrollBehaviorTopAppBar に指定します。
  3. スクロール可能なコンテンツが上下にスクロールするときに、Scaffold がネストされたスクロール イベントを受信できるように、ScaffoldModifier.nestedScroll を介して NestedScrollConnection を接続します。こうすることで、コンクリート アプリバーが コンテンツのスクロールに合わせて適切に折りたたまれたり開いたりします。

    // 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 のネストされたスクロール サンプルをご覧ください。 見てみましょう。

ドロワー

ビューを使用する場合は、DrawerLayout をルートビューとして使用してナビゲーション ドロワーを実装します。CoordinatorLayoutDrawerLayout の子ビューです。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
        // ...
    }
}

詳しくは、ドロワーをご覧ください。

スナックバー

ScaffoldsnackbarHost スロットを提供します。これは、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 に移行する方法について詳しくは、次のリソースをご覧ください。