CoordinatorLayout
是一个 ViewGroup
,可实现复杂的、重叠的嵌套布局。它用作容器,可实现特定的 Material Design 交互,例如展开/折叠工具栏和其所包含视图的底部抽屉式导航栏。
在 Compose 中,CoordinatorLayout
最接近的等效项是 Scaffold
。Scaffold
为将 Material Components 组合到常见屏幕模式和交互中提供内容槽。本页面介绍如何将 CoordinatorLayout
实现迁移到 Compose 中的 Scaffold
。
迁移步骤
要将 CoordinatorLayout
迁移到 Scaffold
,请按以下步骤操作
在下面的代码段中,
CoordinatorLayout
包含一个AppBarLayout
用于包含ToolBar
、一个ViewPager
和一个FloatingActionButton
。从您的 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" />
在您的 Fragment 或 Activity 中,获取对您刚刚添加的
ComposeView
的引用,并对其调用setContent
方法。在该方法的主体中,将Scaffold
设置为其内容composeView.setContent { Scaffold(Modifier.fillMaxSize()) { contentPadding -> // Scaffold contents // ... } }
在
Scaffold
的内容中,添加屏幕的主要内容。因为上面 XML 中的主要内容是ViewPager2
,我们将使用HorizontalPager
,它是它的 Compose 等效项。Scaffold
的content
lambda 也会收到一个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 */ } } }
常见用例
折叠和展开工具栏
在视图系统中,要使用 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
槽,为屏幕内容提供了一个 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 // ... } }
要了解详情,请参阅抽屉式导航栏。
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 的更多信息,请参阅以下资源
- Material Components 和布局:有关 Compose 中支持的 Material Design 组件(如
Scaffold
)的文档。 - 将 Sunflower 迁移到 Jetpack Compose:一篇博客文章,记录了 Sunflower 示例应用从视图到 Compose 的迁移历程,其中包含一个
CoordinatorLayout
。
为您推荐
- 注意:禁用 JavaScript 时会显示链接文本
- Material Components 和布局
- Compose 中的窗口内边距
- 滚动