CoordinatorLayout 是一种 ViewGroup,可实现复杂、重叠和嵌套的布局。它用作容器,以针对其中包含的视图启用特定的 Material Design 互动,例如展开/收起工具栏和底部动作条。
在 Compose 中,最接近 CoordinatorLayout 的等效项是 Scaffold。Scaffold 提供内容槽,用于将 Material 组件组合成常见的屏幕图案和互动。本页介绍了如何迁移 CoordinatorLayout 实现以在 Compose 中使用 Scaffold。
迁移步骤
如需将 CoordinatorLayout 迁移到 Scaffold,请按以下步骤操作:
在以下代码段中,
CoordinatorLayout包含一个AppBarLayout,用于包含ToolBar、ViewPager和FloatingActionButton。从界面层次结构中注释掉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" />在您的 fragment 或 activity 中,获取对您刚刚添加的
ComposeView的引用,并对其调用setContent方法。在方法正文中,将Scaffold设置为内容:composeView.setContent { Scaffold(Modifier.fillMaxSize()) { contentPadding -> // Scaffold contents // ... } }
在
Scaffold的内容中,添加屏幕的主要内容。由于上述 XML 中的主要内容是ViewPager2,因此我们将使用HorizontalPager,它是 Compose 中与之等效的元素。Scaffold的contentlambda 还会接收一个应应用于内容根目录的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提供的其他内容 slot 添加更多屏幕元素,并迁移剩余的子视图。您可以使用topBarslot 添加TopAppBar,并使用floatingActionButtonslot 提供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 */ } } }
常见用例
收起和展开工具栏
在视图系统中,如需使用 CoordinatorLayout 收起和展开工具栏,您可以使用 AppBarLayout 作为工具栏的容器。然后,您可以通过关联的可滚动视图(例如 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 还提供其他 TopAppBarScrollBehavior,例如 exitUntilCollapsedScrollBehavior,它仅在内容滚动到底部时展开应用栏。
如需创建完全自定义的效果(例如,视差效果),您还可以创建自己的 NestedScrollConnection,并在内容滚动时手动偏移工具栏。如需查看代码示例,请参阅 AOSP 上的嵌套滚动示例。
抽屉
使用视图时,您可以使用 DrawerLayout 作为根视图来实现抽屉式导航栏。反过来,您的 CoordinatorLayout 是 DrawerLayout 的子视图。DrawerLayout 还包含另一个子视图(例如 NavigationView),用于在抽屉式导航栏中显示导航选项。
在 Compose 中,您可以使用 ModalNavigationDrawer 可组合项实现抽屉式导航栏。ModalNavigationDrawer 为抽屉式导航栏提供 drawerContent slot,为屏幕内容提供 content slot。
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 slot,该 slot 可接受 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 // ... }
如需了解详情,请参阅信息栏。
了解详情
如需详细了解如何将 CoordinatorLayout 迁移到 Compose,请参阅以下资源:
- Material 组件和布局:有关 Compose 中支持的 Material Design 组件(例如
Scaffold)的文档。 - 将 Sunflower 迁移到 Jetpack Compose:一篇博文,记录了 Sunflower 示例应用从 View 到 Compose 的迁移过程,其中包含
CoordinatorLayout。
为您推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- Material 组件和布局
- Compose 中的窗口边衬区
- 滚动