將 CoordinatorLayout 遷移至 Compose

CoordinatorLayout 是一個 ViewGroup,可以建立複雜、重疊和 以及巢狀版面配置的結構可用做容器來啟用特定 Material Design 互動情形,例如展開/收合工具列和底部功能表 特定資料或檔案

在 Compose 中,最接近的 CoordinatorLayoutScaffoldScaffold 提供用於合併 Material 的內容版位 將元件轉換為常見的螢幕模式和互動。本頁說明 就能遷移CoordinatorLayout實作項目,Scaffold在 。

遷移步驟

如要將 CoordinatorLayout 遷移至 Scaffold,請按照下列步驟操作:

  1. 在下列程式碼片段中,CoordinatorLayout 包含以下項目的 AppBarLayout: 其中包含 ToolBarViewPagerFloatingActionButton。註解 從 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. 在 Fragment 或 Activity 中,取得對 ComposeView 的參照 並在其上呼叫 setContent 方法。在方法主體中 將 Scaffold 設為內容:

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

  3. 在「Scaffold」的內容中新增螢幕的主要內容 基礎架構由於上述 XML 中的主要內容是 ViewPager2,因此我們將使用 HorizontalPager,相當於 Compose。content lambda 的 Scaffold 也會收到 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. 將建立的 TopAppBarScrollBehavior 提供給 TopAppBar
  3. 透過右側的 Modifier.nestedScroll 連結 NestedScrollConnection Scaffold,讓 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 人 提供其他 TopAppBarScrollBehavior,例如 exitUntilCollapsedScrollBehavior,只有在出現以下情況時,才會展開應用程式列 捲動瀏覽內容

如要建立完全自訂的效果 (例如視差效果),您可以 您也可以建立自己的 NestedScrollConnection,並手動調整工具列,如 內容會捲動顯示詳情請參閱 Android 開放原始碼計畫的巢狀捲動範例 做為參考依據

導覽匣

在 View 中,您可以使用導覽匣 DrawerLayout 做為根層級檢視畫面。因此,CoordinatorLayoutDrawerLayout 的子項檢視畫面。DrawerLayout 中也包含另一個子項 檢視畫面 (例如 NavigationView),即可在 導覽匣。

在 Compose 中,您可以使用 ModalNavigationDrawer 可組合函式。ModalNavigationDrawer提供 導覽匣 drawerContent 版位,螢幕的 content 版位 內容。

ModalNavigationDrawer(
    drawerContent = {
        ModalDrawerSheet {
            Text("Drawer title", modifier = Modifier.padding(16.dp))
            Divider()
            NavigationDrawerItem(
                label = { Text(text = "Drawer Item") },
                selected = false,
                onClick = { /*TODO*/ }
            )
            // ...other drawer items
        }
    }
) {
    Scaffold(Modifier.fillMaxSize()) { contentPadding ->
        // Scaffold content
        // ...
    }
}

詳情請參閱「導覽匣」。

Snackbar

Scaffold 提供 snackbarHost 版位,可接受 SnackbarHost 可顯示 Snackbar 的可組合函式。

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
    // ...
}

詳情請參閱 Snackbar

瞭解詳情

如要進一步瞭解如何將 CoordinatorLayout 遷移至 Compose,請參閱 下列資源: