“列表-详情”是一种由双窗格布局组成的界面模式,其中,一个窗格显示项目列表,另一个窗格显示从列表中选择的项目的详细信息。
此模式对于提供大型集合元素相关深入信息的应用特别有用,例如,包含电子邮件列表和每封电子邮件详细内容的电子邮件客户端。“列表-详情”也可用于不太重要的路径,例如将应用偏好设置划分为一系列类别,并在详情窗格中为每个类别设定偏好设置。
使用 ListDetailPaneScaffold
实现界面模式
ListDetailPaneScaffold
是一个可组合项,它简化了应用中“列表-详情”模式的实现。“列表-详情”基架最多可由三个窗格组成:列表窗格、详情窗格和可选的额外窗格。基架会处理屏幕空间的计算。当有充足的屏幕尺寸时,详情窗格会与列表窗格一同显示。在小尺寸屏幕上,基架会自动切换为以全屏模式显示列表窗格或详情窗格。
声明依赖项
ListDetailPaneScaffold
是 Material 3 自适应布局库的一部分。
您的应用必须包含三个相关 Material 3 库的依赖项:
- 自适应 - 低层级构建块,例如
HingeInfo
和Posture
- adaptive-layout - 自适应布局,例如
ListDetailPaneScaffold
和SupportingPaneScaffold
- adaptive-navigation - 用于在窗格内和窗格之间导航的可组合项
将依赖项添加到应用或模块的 build.gradle
文件中:
Kotlin
implementation("androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12") implementation("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha12") implementation("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha12")
Groovy
implementation 'androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12' implementation 'androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha12' implementation 'androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha12'
基本用法
按如下方式实现 ListDetailPaneScaffold
:
使用一个类来表示要选择的内容。此类应为
Parcelable
,以支持保存和恢复所选列表项。使用 kotlin-parcelize 插件为您生成代码。@Parcelize class MyItem(val id: Int) : Parcelable
使用
rememberListDetailPaneScaffoldNavigator
创建ThreePaneScaffoldNavigator
并添加BackHandler
。此导航器用于在列表窗格、详情窗格和其他窗格之间移动。通过声明泛型类型,导航器还可以跟踪基架的状态(即显示的是哪个MyItem
)。由于此类型是 Parcelable,因此导航器可以保存和恢复状态,以自动处理配置更改。BackHandler
支持使用系统返回手势或按钮返回。ListDetailPaneScaffold
的返回按钮的预期行为取决于窗口大小和当前的 Scaffold 值。如果ListDetailPaneScaffold
可以支持返回当前状态,则canNavigateBack()
为true
,从而启用BackHandler
。val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() }
将
scaffoldState
从navigator
传递给ListDetailPaneScaffold
可组合项。ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, // ... )
将您的列表窗格实现提供给
ListDetailPaneScaffold
。 使用AnimatedPane
在导航期间应用默认窗格动画。然后使用ThreePaneScaffoldNavigator
前往详细信息窗格ListDetailPaneScaffoldRole.Detail
,并显示传递的项。ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane { MyList( onItemClick = { item -> // Navigate to the detail pane with the passed item navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) } ) } }, // ... )
在
ListDetailPaneScaffold
中添加详情窗格实现。 导航完成后,currentDestination
包含应用已导航到的窗格,包括该窗格中显示的内容。content
属性与原始 remember 调用(在本例中为MyItem
)中指定的类型相同,因此您还可以访问需要显示的任何数据的属性。ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = // ... detailPane = { AnimatedPane { navigator.currentDestination?.content?.let { MyDetails(it) } } }, )
实现上述步骤后,您的代码应如下所示:
val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() } ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane { MyList( onItemClick = { item -> // Navigate to the detail pane with the passed item navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) }, ) } }, detailPane = { AnimatedPane { // Show the detail pane content if selected item is available navigator.currentDestination?.content?.let { MyDetails(it) } } }, )