Bố cục ngăn bổ trợ giúp người dùng tập trung vào nội dung chính của ứng dụng trong khi hiển thị thông tin hỗ trợ có liên quan. Ví dụ: ngăn chính có thể hiển thị thông tin chi tiết về một bộ phim, trong khi ngăn hỗ trợ liệt kê các bộ phim tương tự, phim của cùng một đạo diễn hoặc tác phẩm có cùng diễn viên.
Để biết thêm thông tin, hãy xem nguyên tắc về ngăn hỗ trợ của Material 3.
Triển khai ngăn hỗ trợ bằng scaffold
NavigableSupportingPaneScaffold là một thành phần kết hợp giúp đơn giản hoá việc triển khai bố cục ngăn hỗ trợ trong Jetpack Compose. Thành phần này gói gọn SupportingPaneScaffold, đồng thời bổ sung tính năng điều hướng tích hợp sẵn và xử lý cử chỉ xem trước thao tác quay lại.
Một ngăn hỗ trợ có thể hỗ trợ tối đa 3 ngăn:
- Ngăn chính: Hiển thị nội dung chính.
- Ngăn bổ trợ: Cung cấp thêm bối cảnh hoặc công cụ liên quan đến ngăn chính.
- Ngăn bổ sung (không bắt buộc): Dùng cho nội dung bổ sung khi cần.
Scaffold điều chỉnh dựa trên kích thước cửa sổ:
- Trong cửa sổ lớn, ngăn chính và ngăn bổ trợ xuất hiện cạnh nhau.
Trong cửa sổ nhỏ, mỗi lần chỉ có một ngăn hiển thị, chuyển đổi khi người dùng di chuyển.
Hình 1. Bố cục ngăn bổ trợ.
Thêm phần phụ thuộc
NavigableSupportingPaneScaffold là một phần của thư viện bố cục thích ứng Material 3.
Thêm ba phần phụ thuộc có liên quan sau đây vào tệp build.gradle của ứng dụng hoặc mô-đun:
Kotlin
implementation("androidx.compose.material3.adaptive:adaptive")
implementation("androidx.compose.material3.adaptive:adaptive-layout")
implementation("androidx.compose.material3.adaptive:adaptive-navigation")
Groovy
implementation 'androidx.compose.material3.adaptive:adaptive'
implementation 'androidx.compose.material3.adaptive:adaptive-layout'
implementation 'androidx.compose.material3.adaptive:adaptive-navigation'
adaptive-layout: Bố cục thích ứng, chẳng hạn như
ListDetailPaneScaffoldvàSupportingPaneScaffoldadaptive-navigation: Các thành phần kết hợp để điều hướng trong và giữa các ngăn, cũng như bố cục thích ứng hỗ trợ điều hướng theo mặc định, chẳng hạn như
NavigableListDetailPaneScaffoldvàNavigableSupportingPaneScaffold
Xác minh rằng dự án của bạn có chứa compose-material3-adaptive phiên bản 1.1.0-beta1 trở lên.
Chọn sử dụng tính năng xem trước thao tác quay lại
Để bật ảnh động xem trước thao tác quay lại trong Android 15 trở xuống, bạn phải chọn sử dụng tính năng hỗ trợ xem trước thao tác quay lại. Để chọn sử dụng, hãy thêm
android:enableOnBackInvokedCallback="true" vào thẻ <application> hoặc
từng thẻ <activity> trong tệp AndroidManifest.xml.
Khi ứng dụng của bạn nhắm đến Android 16 (cấp độ API 36) trở lên, tính năng xem trước thao tác quay lại sẽ được bật theo mặc định.
Tạo trình điều hướng
Trong cửa sổ nhỏ, mỗi lần chỉ có một ngăn hiển thị, vì vậy, hãy sử dụng ThreePaneScaffoldNavigator để di chuyển đến và đi từ các ngăn. Tạo một thực thể của trình điều hướng bằng rememberSupportingPaneScaffoldNavigator.
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope()
Truyền trình điều hướng đến scaffold
Scaffold yêu cầu một ThreePaneScaffoldNavigator, là một giao diện đại diện cho trạng thái của scaffold, ThreePaneScaffoldValue và PaneScaffoldDirective.
NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { /*...*/ }, supportingPane = { /*...*/ }, )
Ngăn chính và ngăn bổ trợ là các thành phần kết hợp chứa nội dung của bạn. Sử dụng AnimatedPane để áp dụng ảnh động mặc định của ngăn trong quá trình điều hướng. Sử dụng giá trị scaffold để kiểm tra xem ngăn hỗ trợ có bị ẩn hay không; nếu có, hãy hiển thị một nút gọi navigateTo(SupportingPaneScaffoldRole.Supporting) để hiển thị ngăn hỗ trợ.
Đối với màn hình lớn, hãy sử dụng phương thức ThreePaneScaffoldNavigator.navigateBack() để đóng ngăn hỗ trợ, truyền hằng số BackNavigationBehavior.PopUntilScaffoldValueChange. Việc gọi phương thức này sẽ buộc tái kết hợp NavigableSupportingPaneScaffold.
Trong quá trình kết hợp lại, hãy kiểm tra thuộc tính ThreePaneScaffoldNavigator.currentDestination để xác định xem có hiển thị ngăn hỗ trợ hay không.
Dưới đây là cách triển khai hoàn chỉnh của scaffold:
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() val backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { AnimatedPane( modifier = Modifier .safeContentPadding() .background(Color.Red) ) { if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden) { Button( modifier = Modifier .wrapContentSize(), onClick = { scope.launch { scaffoldNavigator.navigateTo(SupportingPaneScaffoldRole.Supporting) } } ) { Text("Show supporting pane") } } else { Text("Supporting pane is shown") } } }, supportingPane = { AnimatedPane(modifier = Modifier.safeContentPadding()) { Column { // Allow users to dismiss the supporting pane. Use back navigation to // hide an expanded supporting pane. if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) { // Material design principles promote the usage of a right-aligned // close (X) button. IconButton( modifier = Modifier.align(Alignment.End).padding(16.dp), onClick = { scope.launch { scaffoldNavigator.navigateBack(backNavigationBehavior) } } ) { Icon(Icons.Default.Close, contentDescription = "Close") } } Text("Supporting pane") } } } )
Trích xuất các thành phần kết hợp của ngăn
Trích xuất từng ngăn của SupportingPaneScaffold vào các thành phần kết hợp riêng để có thể sử dụng lại và kiểm thử. Sử dụng ThreePaneScaffoldScope để truy cập vào AnimatedPane nếu bạn muốn dùng ảnh động mặc định:
@OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable fun ThreePaneScaffoldPaneScope.MainPane( shouldShowSupportingPaneButton: Boolean, onNavigateToSupportingPane: () -> Unit, modifier: Modifier = Modifier, ) { AnimatedPane( modifier = modifier.safeContentPadding() ) { // Main pane content if (shouldShowSupportingPaneButton) { Button(onClick = onNavigateToSupportingPane) { Text("Show supporting pane") } } else { Text("Supporting pane is shown") } } } @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable fun ThreePaneScaffoldPaneScope.SupportingPane( scaffoldNavigator: ThreePaneScaffoldNavigator<Any>, modifier: Modifier = Modifier, backNavigationBehavior: BackNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange, ) { val scope = rememberCoroutineScope() AnimatedPane(modifier = Modifier.safeContentPadding()) { Column { // Allow users to dismiss the supporting pane. Use back navigation to // hide an expanded supporting pane. if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) { // Material design principles promote the usage of a right-aligned // close (X) button. IconButton( modifier = modifier.align(Alignment.End).padding(16.dp), onClick = { scope.launch { scaffoldNavigator.navigateBack(backNavigationBehavior) } } ) { Icon(Icons.Default.Close, contentDescription = "Close") } } Text("Supporting pane") } } }
Việc trích xuất các ngăn thành thành phần kết hợp sẽ đơn giản hoá việc sử dụng SupportingPaneScaffold (so sánh nội dung sau đây với cách triển khai hoàn chỉnh của scaffold trong phần trước):
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { MainPane( shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden, onNavigateToSupportingPane = { scope.launch { scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary) } } ) }, supportingPane = { SupportingPane(scaffoldNavigator = scaffoldNavigator) }, )
Nếu bạn cần kiểm soát nhiều hơn đối với các khía cạnh cụ thể của scaffold, hãy cân nhắc sử dụng SupportingPaneScaffold thay vì NavigableSupportingPaneScaffold. Hàm này chấp nhận PaneScaffoldDirective và ThreePaneScaffoldValue hoặc ThreePaneScaffoldState riêng biệt. Tính linh hoạt này cho phép bạn triển khai logic tuỳ chỉnh cho khoảng cách giữa các ngăn và xác định số lượng ngăn sẽ hiển thị đồng thời. Bạn cũng có thể bật tính năng hỗ trợ xem trước thao tác quay lại bằng cách thêm ThreePaneScaffoldPredictiveBackHandler.
Thêm ThreePaneScaffoldPredictiveBackHandler
Đính kèm trình xử lý xem trước thao tác quay lại, lấy một thực thể trình điều hướng scaffold và chỉ định backBehavior. Thao tác này xác định cách các đích đến được kéo ra khỏi ngăn xếp lui trong quá trình điều hướng quay lại. Sau đó, hãy truyền scaffoldDirective và scaffoldState đến SupportingPaneScaffold. Sử dụng phương thức nạp chồng chấp nhận ThreePaneScaffoldState, truyền vào scaffoldNavigator.scaffoldState.
Xác định ngăn chính và ngăn hỗ trợ trong SupportingPaneScaffold. Sử dụng AnimatedPane cho ảnh động của ngăn mặc định.
Sau khi bạn triển khai các bước này, mã của bạn sẽ có dạng như sau:
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() ThreePaneScaffoldPredictiveBackHandler( navigator = scaffoldNavigator, backBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange ) SupportingPaneScaffold( directive = scaffoldNavigator.scaffoldDirective, scaffoldState = scaffoldNavigator.scaffoldState, mainPane = { MainPane( shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden, onNavigateToSupportingPane = { scope.launch { scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary) } } ) }, supportingPane = { SupportingPane(scaffoldNavigator = scaffoldNavigator) }, )