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à ngăn còn lại 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 chuyên sâu về các phần tử của tập hợp lớn, ví dụ: ứ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 bố cục 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 lựa chọn ưu tiên của ứng dụng thành một danh sách các danh mục, trong đó các lựa chọn ưu tiên cho từng danh mục nằm 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 gọn ListDetailPaneScaffold và thêm ảnh động xem trước thao tác quay lại và điều hướng tích hợp sẵn.
Khung danh sách-chi tiết hỗ trợ tối đa 3 ngăn:
- Ngăn danh sách: Hiển thị một tập hợp các mục.
- Ngăn chi tiết: Cho thấy thông tin chi tiết về một mục đã chọn.
- Ngăn bổ sung (không bắt buộc): Cung cấp thêm bối cảnh 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 danh sách và ngăn chi tiết sẽ 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.
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 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'
- thích ứng: Các thành phần cấp thấp như
HingeInfovàPosture - adaptive-layout: Bố cục thích ứng, chẳng hạn như
ListDetailPaneScaffoldvàSupportingPaneScaffold - adaptive-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
Đảm bảo dự án của bạn có 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
các thẻ <activity> riêng lẻ trong tệp AndroidManifest.xml. Để biết thêm thông tin, hãy xem phần Chọn sử dụng tính năng xem trước thao tác quay lại.
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 một
ThreePaneScaffoldNavigatorbằngrememberListDetailPaneScaffoldNavigator.
Trình điều hướng này được dùng để di chuyển giữa danh sách, chi tiết và các ngăn bổ sung. Bằng cách khai báo một loại chung, trình điều hướng cũng theo dõi trạng thái của scaffold (tức là MyItem nào đang được hiển thị). Vì loại này có thể phân chia, nên trình điều hướng có thể lưu và khôi phục trạng thái để 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 cách triển khai ngăn danh sách cho
NavigableListDetailPaneScaffold. Sử dụngAnimatedPaneđể áp dụng ảnh động mặc định của ngăn trong quá trình điều hướng. Sau đó, hãy sử dụngThreePaneScaffoldNavigatorđể chuyển đến ngăn chi tiết,ListDetailPaneScaffoldRole.Detailvà hiển thị mục đã truyền.Đưa phương thứ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 đã điều hướng đến, bao gồm cả nội dung hiển thị trong ngăn. Thuộc tính contentKey có cùng loại được chỉ định trong lệnh gọi ban đầu để 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 các 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 sẽ 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 nào về bố cục để huỷ bỏ trong bối cảnh hiện tại. Trong bố cục một ngăn, thao tá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ì điều này thể hiện sự 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 bạn nhấp vào một email khác (Mục 2), ngăn chi tiết sẽ được cập nhật, nhưng ngăn danh sách và ngăn chi tiết vẫn hiển thị. Thao tác nhấn nút quay lại có thể thoát khỏi ứng dụng hoặc quy trình điều hướng hiện tại.
- Một ngăn: Bạn xem Mục 1, sau đó xem Mục 2, nhấn nút quay lại sẽ đưa bạn trực tiếp đến ngăn danh sách email.
Hãy sử dụng chế độ này khi bạn muốn người dùng nhận thấy các hiệu ứng 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 được hiển thị. Nếu bạn xem Mục 1 rồi đến Mục 2, thì thao tác nhấn nút quay lại sẽ đưa bạn về 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. Thao tác nhấn nút quay lại sẽ khôi phục ngăn chi tiết về Mục 1.
- Một ngăn: Nội dung cũng được khôi phục tương tự.
Hãy sử dụng chế độ này khi người dùng 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ẽ bật ngăn xếp lui cho đến khi đích điều hướng hiện tại thay đổi. Điều này áp dụng như nhau cho bố cục một 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 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 làm nổi bật đến đích đến trước đó. Trong ứng dụng email, điều này có nghĩa là chỉ báo trực quan của ngăn đã chọn sẽ thay đổi.
Hãy sử dụng chế độ này khi việc duy trì chỉ báo hình ảnh rõ ràng về thành phần điều hướng hiện tại là yếu 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 bạn triển khai các bước này, mã của bạn sẽ có dạ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 ) } } ) } }