Danh sách-chi tiết là một mẫu giao diện người dùng bao gồm bố cục hai ngăn, trong đó một ngăn trình bày danh sách các mục và một ngăn hiển thị thông tin chi tiết của các mục được chọn trong danh sách.
Mẫu này đặc biệt hữu ích cho các ứng dụng cung cấp thông tin chi tiết về các phần tử của bộ sưu tập lớn, ví dụ: một ứng dụng email có danh sách email và nội dung chi tiết của từng nội dung email. Bạn cũng có thể sử dụng mẫu danh sách-chi tiết cho các đường dẫn ít quan trọng hơn, chẳng hạn như chia các tuỳ chọn ưu tiên của ứng dụng thành danh sách các danh mục với các tuỳ chọn ưu tiên cho từng danh mục trong ngăn chi tiết.
Triển khai mẫu danh sách-chi tiết bằng NavigableListDetailPaneScaffold
NavigableListDetailPaneScaffold 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 danh sách-chi tiết trong Jetpack Compose. Thành phần này gói ListDetailPaneScaffold và thêm ảnh động xem trước thao tác quay lại cũng như ảnh động điều hướng tích hợp sẵn.
Khung hiển thị danh sách-chi tiết hỗ trợ tối đa 3 ngăn:
- Ngăn danh sách: Hiển thị một bộ sưu tập các mục.
- Ngăn chi tiết: Hiển thị thông tin chi tiết của một mục đã chọn.
- Ngăn bổ sung (không bắt buộc): Cung cấp thêm ngữ cảnh khi cần.
Khung hiển thị này sẽ điều chỉnh dựa trên kích thước cửa sổ:
- Trong các cửa sổ lớn, ngăn danh sách và ngăn chi tiết sẽ xuất hiện cạnh nhau.
- Trong các 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.
Khai báo phần phụ thuộc
NavigableListDetailPaneScaffold là một phần của thư viện điều hướng thích ứng Material 3.
Thêm 3 phần phụ thuộc liên quan sau 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: Các thành phần cấp thấp như
HingeInfovàPosture - adaptive-layout: Bố cục thích ứng như
ListDetailPaneScaffoldvàSupportingPaneScaffold - adaptive-navigation: Các thành phần kết hợp để di chuyển trong và giữa các ngăn, cũng như các bố cục thích ứng hỗ trợ tính năng điều hướng theo mặc định như
NavigableListDetailPaneScaffoldvàNavigableSupportingPaneScaffold
Đảm bảo dự án của bạn có phiên bản compose-material3-adaptive 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
các thẻ <activity> riêng lẻ trong tệp AndroidManifest.xml. Để biết thêm
thông tin, hãy xem bài viết Chọn sử dụng tính năng xem trước thao tác quay lại.
Sau 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.
Cách sử dụng cơ bản
Triển khai NavigableListDetailPaneScaffold như sau:
- Sử dụng một lớp đại diện cho nội dung đã chọn. Sử dụng lớp
Parcelableđể hỗ trợ lưu và khôi phục mục danh sách đã chọn. Sử dụng trình bổ trợ kotlin-parcelize để tạo mã cho bạn. - Tạo
ThreePaneScaffoldNavigatorbằngrememberListDetailPaneScaffoldNavigator.
Trình điều hướng này được dùng để di chuyển giữa các ngăn danh sách, chi tiết và bổ sung. Bằng cách khai báo một kiểu chung, trình điều hướng cũng theo dõi trạng thái của khung hiển thị (tức là MyItem nào đang được hiển thị). Vì kiểu này có thể được phân tích cú pháp, nên trạng thái có thể được trình điều hướng lưu và khôi phục để tự động xử lý các thay đổi về cấu hình.
Truyền trình điều hướng đến thành phần kết hợp
NavigableListDetailPaneScaffold.Cung cấp việc triển khai ngăn danh sách cho
NavigableListDetailPaneScaffold. Sử dụngAnimatedPaneđể áp dụng ảnh động ngăn mặc định trong quá trình điều hướng. Sau đó, sử dụngThreePaneScaffoldNavigatorđể di chuyển đến ngăn chi tiết,ListDetailPaneScaffoldRole.Detailvà hiển thị mục đã truyền.Đưa việc triển khai ngăn chi tiết vào
NavigableListDetailPaneScaffold.
Khi quá trình điều hướng hoàn tất, currentDestination sẽ chứa ngăn mà ứng dụng của bạn đã di chuyển đến, bao gồm cả nội dung hiển thị trong ngăn đó. Thuộc tính contentKey có cùng kiểu được chỉ định trong lệnh gọi ban đầu, vì vậy, bạn có thể truy cập vào mọi dữ liệu cần hiển thị.
- Bạn có thể thay đổi
defaultBackBehaviortrongNavigableListDetailPaneScaffold. Theo mặc định,NavigableListDetailPaneScaffoldsử dụngPopUntilScaffoldValueChangechodefaultBackBehavior.
Nếu ứng dụng của bạn yêu cầu một mẫu điều hướng quay lại khác, bạn có thể ghi đè hành vi này bằng cách chỉ định một tuỳ chọn BackNavigationBehavior khác.
Tuỳ chọn BackNavigationBehavior
Phần sau đây sử dụng ví dụ về một ứng dụng email có danh sách email trong một ngăn và chế độ xem chi tiết trong ngăn còn lại.
PopUntilScaffoldValueChange (Mặc định và nên dùng trong hầu hết các trường hợp)
Hành vi này tập trung vào những thay đổi đối với cấu trúc bố cục tổng thể. Trong chế độ thiết lập nhiều ngăn, việc thay đổi nội dung email trong ngăn chi tiết không làm thay đổi cấu trúc bố cục cơ bản. Do đó, nút quay lại có thể thoát khỏi ứng dụng hoặc biểu đồ điều hướng hiện tại vì không có thay đổi bố cục nào để quay lại trong ngữ cảnh hiện tại. Trong bố cục một ngăn, việc nhấn nút quay lại sẽ bỏ qua các thay đổi về nội dung trong chế độ xem chi tiết và quay lại chế độ xem danh sách, vì đây là một thay đổi rõ ràng về bố cục.
Hãy xem các ví dụ sau đây:
- Nhiều ngăn: Bạn đang xem một email (Mục 1) trong ngăn chi tiết. Khi nhấp vào một email khác (Mục 2), ngăn chi tiết sẽ cập nhật, nhưng ngăn danh sách và ngăn chi tiết vẫn hiển thị. Việc nhấn nút quay lại có thể thoát khỏi ứng dụng hoặc luồng điều hướng hiện tại.
- Một ngăn: Bạn xem Mục 1, sau đó là Mục 2, khi nhấn nút quay lại, bạn sẽ được đưa trực tiếp đến ngăn danh sách email.
Sử dụng tuỳ chọn này khi bạn muốn người dùng nhận thấy các quá trình chuyển đổi bố cục riêng biệt với mỗi thao tác quay lại.
PopUntilContentChange
Hành vi này ưu tiên nội dung hiển thị. Nếu bạn xem Mục 1 rồi xem Mục 2, thì khi nhấn nút quay lại, hệ thống sẽ quay lại Mục 1, bất kể bố cục.
Hãy xem các ví dụ sau đây:
- Nhiều ngăn: Bạn xem Mục 1 trong ngăn chi tiết, sau đó nhấp vào Mục 2 trong danh sách. Ngăn chi tiết sẽ cập nhật. Khi nhấn nút quay lại, ngăn chi tiết sẽ khôi phục về Mục 1.
- Một ngăn: Quá trình quay lại nội dung tương tự sẽ xảy ra.
Sử dụng tuỳ chọn này khi người dùng mong muốn quay lại nội dung đã xem trước đó bằng thao tác quay lại.
PopUntilCurrentDestinationChange
Hành vi này sẽ đẩy ngăn xếp lui cho đến khi đích đến điều hướng hiện tại thay đổi. Điều này áp dụng cho cả bố cục một ngăn và nhiều ngăn.
Hãy xem các ví dụ sau đây:
Bất kể bạn đang ở bố cục một ngăn hay nhiều ngăn, việc nhấn nút quay lại sẽ luôn di chuyển tiêu điểm từ phần tử điều hướng được đánh dấu sang đích đến trước đó. Trong ứng dụng email của chúng tôi, điều này có nghĩa là chỉ báo trực quan về ngăn đã chọn sẽ thay đổi.
Sử dụng tuỳ chọn này khi việc duy trì chỉ báo trực quan rõ ràng về quá trình điều hướng hiện tại là rất quan trọng đối với trải nghiệm người dùng.
PopLatest
Tuỳ chọn này chỉ xoá đích đến gần đây nhất khỏi ngăn xếp lui. Sử dụng tuỳ chọn này để điều hướng quay lại mà không bỏ qua các trạng thái trung gian.
Sau khi triển khai các bước này, mã của bạn sẽ trông giống như sau:
NavigableListDetailPaneScaffold( navigator = navigator, listPane = { AnimatedPane { ListContent( words = sampleWords, selectionState = navigator.currentDestination?.contentKey?.let { SelectionVisibilityState.ShowSelection(it) } ?: SelectionVisibilityState.NoSelection, onWordClick = { word -> scope.launch { navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, word) } }, animatedVisibilityScope = this@AnimatedPane, sharedTransitionScope = this@SharedTransitionLayout ) } }, detailPane = { AnimatedPane { DetailContent( definedWord = navigator.currentDestination?.contentKey, animatedVisibilityScope = this@AnimatedPane, sharedTransitionScope = this@SharedTransitionLayout, onClosePane = { scope.launch { navigator.navigateBack( backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange ) } } ) } }