清單/詳細資料是一種 UI 模式,由雙窗格版面配置組成,其中一個窗格顯示項目清單,另一個窗格則顯示清單中所選項目的詳細資料。
如果應用程式需要深入瞭解大型集合的元素資訊,例如電子郵件用戶端含有電子郵件清單和每封電子郵件的詳細內容,這個模式就特別實用。清單詳細資料也可用於較不重要的路徑,例如將應用程式偏好設定區分為類別清單,以及詳細資料窗格中各類別的偏好設定。
使用 ListDetailPaneScaffold
實作 UI 模式
ListDetailPaneScaffold
是一種可組合項,可簡化應用程式中「清單/詳細資料」模式的實作方式。清單詳細資料 Scaffold 最多可包含三個窗格:清單窗格、詳細資料窗格和選用的額外窗格。Scaffold 會處理螢幕空間計算。如果可用螢幕大小足夠,詳細資料窗格會顯示在清單窗格旁。在小螢幕上,Sscaffold 會自動切換為全螢幕顯示清單或詳細資料窗格。
宣告依附元件
ListDetailPaneScaffold
是 Material 3 自動調整程式庫的一部分。在應用程式或模組的 build.gradle
檔案中,新增程式庫的依附元件:
implementation("androidx.compose.material3.adaptive:adaptive:1.0.0-alpha07")
implementation("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha07")
implementation("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha07")
基本用法
以下說明 ListDetailPaneScaffold
的基本用法:
將目前從清單中選取的項目儲存在可變動狀態變數中。變數會存放要在詳細資料窗格中顯示的項目。一般而言,建議您使用
null
初始化目前選取的項目,表示您尚未選取任何項目。class MyItem(val id: Int) { companion object { val Saver: Saver<MyItem?, Int> = Saver( { it?.id }, ::MyItem, ) } }
var selectedItem: MyItem? by rememberSaveable(stateSaver = MyItem.Saver) { mutableStateOf(null) }
使用
rememberListDetailPaneScaffoldNavigator
建立ThreePaneScaffoldNavigator
並新增BackHandler
。這個導覽器是用來在清單、詳細資料和其他窗格之間移動,並將狀態提供給 Scaffold。新增的BackHandler
支援使用系統返回手勢或按鈕返回操作。ListDetailPaneScaffold
返回按鈕的預期行為取決於視窗大小和目前的 Scaffold 值。如果ListDetailPaneScaffold
可支援使用目前狀態返回,則canNavigateBack()
會是true
,並啟用BackHandler
。val navigator = rememberListDetailPaneScaffoldNavigator<Nothing>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() }
將
scaffoldState
從您建立的navigator
傳遞至ListDetailPaneScaffold
可組合項。ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, // ... )
將清單窗格實作提供給
ListDetailPaneScaffold
。請確認實作內容包含回呼引數,以便擷取新選取的項目。觸發此回呼時,請更新selectedItem
狀態變數,並使用ThreePaneScaffoldNavigator
顯示詳細資料窗格 (ListDetailPaneScaffoldRole.Detail
)。ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane(Modifier) { MyList( onItemClick = { id -> // Set current item selectedItem = id // Switch focus to detail pane navigator.navigateTo(ListDetailPaneScaffoldRole.Detail) } ) } }, // ... )
在
ListDetailPaneScaffold
中加入詳細資料窗格實作項目。只有在selectedItem
不是空值時,才會顯示詳細資料內容。ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = // ... detailPane = { AnimatedPane(Modifier) { selectedItem?.let { item -> MyDetails(item) } } }, )
完成上述步驟後,您的程式碼應如下所示:
// Currently selected item var selectedItem: MyItem? by rememberSaveable(stateSaver = MyItem.Saver) { mutableStateOf(null) } // Create the ListDetailPaneScaffoldState val navigator = rememberListDetailPaneScaffoldNavigator<Nothing>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() } ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane(Modifier) { MyList( onItemClick = { id -> // Set current item selectedItem = id // Display the detail pane navigator.navigateTo(ListDetailPaneScaffoldRole.Detail) }, ) } }, detailPane = { AnimatedPane(Modifier) { // Show the detail pane content if selected item is available selectedItem?.let { item -> MyDetails(item) } } }, )