Khi bạn nhắm đến SDK 35 trở lên trên thiết bị chạy Android 15 trở lên, ứng dụng của bạn được hiển thị tràn viền. Cửa sổ trải rộng toàn bộ chiều rộng và chiều cao màn hình bằng cách vẽ phía sau các thanh hệ thống. Thanh hệ thống bao gồm trạng thái thanh phụ đề, thanh phụ đề và thanh điều hướng.
Nhiều ứng dụng có thanh ứng dụng trên cùng. Thanh ứng dụng trên cùng phải kéo dài đến cạnh trên của màn hình và phía sau thanh trạng thái. Thanh ứng dụng trên cùng có thể tuỳ ý thu nhỏ theo chiều cao của thanh trạng thái khi nội dung cuộn.
Nhiều ứng dụng cũng có thanh ứng dụng ở dưới cùng hoặc thanh điều hướng ở dưới cùng. Các thanh này nên đồng thời kéo dài đến cạnh dưới của màn hình và hiển thị phía sau thanh điều hướng thanh. Nếu không, ứng dụng sẽ hiện nội dung cuộn phía sau thanh điều hướng.
Khi triển khai bố cục tràn viền trong ứng dụng của bạn, hãy lưu giữ những nội dung sau trong tâm trí:
- Bật màn hình tràn viền
- Xử lý mọi trường hợp trùng lặp hình ảnh.
- Bạn nên chiếu các màn hình phía sau thanh hệ thống.
![ví dụ về hình ảnh phía sau thanh trạng thái](https://developer.android.google.cn/static/images/guide/navigation/e2e-imagery-behind-status-bar.png?authuser=9&hl=vi)
Cho phép hiển thị tràn viền
Nếu ứng dụng của bạn nhắm đến SDK 35 trở lên, thì chế độ hiển thị tràn viền sẽ tự động được bật cho Thiết bị chạy Android 15 trở lên.
Để bật chế độ hiển thị tràn viền trên các phiên bản Android trước, hãy làm như sau:
Thêm phần phụ thuộc vào Thư viện
androidx.activity
trong Tệpbuild.gradle
của ứng dụng hoặc mô-đun:Kotlin
dependencies { val activity_version =
activity_version
// Java language implementation implementation("androidx.activity:activity:$activity_version") // Kotlin implementation("androidx.activity:activity-ktx:$activity_version") }Groovy
dependencies { def activity_version =
activity_version
// Java language implementation implementation 'androidx.activity:activity:$activity_version' // Kotlin implementation 'androidx.activity:activity-ktx:$activity_version' }Nhập
enableEdgeToEdge
vào ứng dụng của bạn:
Bật tính năng hiển thị tràn viền theo cách thủ công bằng cách gọi enableEdgeToEdge
trong onCreate
/Activity
của bạn. Hàm này phải được gọi trước setContentView
.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) ... }
Java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { EdgeToEdge.enable(this); super.onCreate(savedInstanceState); ... }
Theo mặc định, enableEdgeToEdge()
sẽ làm cho các thanh hệ thống trở nên trong suốt, ngoại trừ
Chế độ thao tác bằng 3 nút, trong đó thanh trạng thái có một màn hình trong suốt. Chiến lược phát hành đĩa đơn
màu của các biểu tượng hệ thống và màn hình được điều chỉnh theo hệ thống
giao diện sáng hoặc tối.
Hàm enableEdgeToEdge()
tự động khai báo rằng ứng dụng phải
được bố trí tràn viền và điều chỉnh màu của thanh hệ thống.
Để bật chế độ hiển thị tràn viền trong ứng dụng mà không cần sử dụng
Hàm enableEdgeToEdge()
, xem
Thiết lập màn hình tràn viền theo cách thủ công.
Xử lý trùng lặp bằng cách sử dụng phần lồng ghép
Một số khung hiển thị của ứng dụng có thể vẽ phía sau thanh hệ thống, như minh hoạ trong hình 3.
Bạn có thể giải quyết các phần chồng chéo bằng cách thể hiện các phần lồng ghép, tức là chỉ định phần nào của màn hình giao với giao diện người dùng hệ thống, chẳng hạn như thanh điều hướng hoặc trạng thái thanh. Giao điểm có thể đồng nghĩa với việc hiển thị phía trên nội dung, nhưng cũng có thể cung cấp thông tin ứng dụng của bạn về cử chỉ hệ thống.
Các loại phần lồng ghép áp dụng để hiện ứng dụng tràn viền là:
Phần lồng ghép thanh hệ thống: phù hợp nhất cho các chế độ xem có thể nhấn và không được bị các thanh hệ thống che khuất về mặt thị giác.
Các phần lồng ghép vết cắt trên màn hình: cho những khu vực có thể có vết cắt trên màn hình do hình dạng của thiết bị.
Phần lồng ghép cử chỉ hệ thống: dành cho các khu vực thao tác bằng cử chỉ mà hệ thống sử dụng được ưu tiên hơn ứng dụng của bạn.
Phần lồng ghép thanh hệ thống
Phần lồng ghép thanh hệ thống là loại phần lồng ghép thường dùng nhất. Chúng đại diện cho khu vực nơi giao diện người dùng hệ thống hiển thị trong trục Z phía trên ứng dụng. Chúng tốt nhất dùng để di chuyển hoặc đệm các khung hiển thị trong ứng dụng của bạn mà bạn có thể nhấn vào và không được bị các thanh hệ thống che khuất trực quan.
Ví dụ: hành động nổi nút (FAB) trong hình 3 là một phần bị thanh điều hướng che khuất:
![ví dụ về triển khai tràn viền, nhưng thanh điều hướng đang che FAB](https://developer.android.google.cn/static/images/guide/navigation/e2e-after-implementation.png?authuser=9&hl=vi)
Để tránh loại hình ảnh trùng lặp này ở chế độ cử chỉ hoặc chế độ nút, bạn
có thể tăng lề của chế độ xem bằng cách sử dụng
getInsets(int)
thông qua tính năng
WindowInsetsCompat.Type.systemBars()
.
Ví dụ về mã sau đây cho thấy cách triển khai phần lồng ghép thanh hệ thống:
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(fab) { v, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) // Apply the insets as a margin to the view. This solution sets // only the bottom, left, and right dimensions, but you can apply whichever // insets are appropriate to your layout. You can also update the view padding // if that's more appropriate. v.updateLayoutParams<MarginLayoutParams> { leftMargin = insets.left, bottomMargin = insets.bottom, rightMargin = insets.right, } // Return CONSUMED if you don't want want the window insets to keep passing // down to descendant views. WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(fab, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); // Apply the insets as a margin to the view. This solution sets only the // bottom, left, and right dimensions, but you can apply whichever insets are // appropriate to your layout. You can also update the view padding if that's // more appropriate. MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams(); mlp.leftMargin = insets.left; mlp.bottomMargin = insets.bottom; mlp.rightMargin = insets.right; v.setLayoutParams(mlp); // Return CONSUMED if you don't want want the window insets to keep passing // down to descendant views. return WindowInsetsCompat.CONSUMED; });
Nếu bạn áp dụng giải pháp này cho ví dụ trong hình 3, kết quả sẽ không chồng chéo hình ảnh ở chế độ nút, như trong hình 4:
![một thanh điều hướng trong suốt không che FAB](https://developer.android.google.cn/static/images/guide/navigation/e2e-system-bars-top.png?authuser=9&hl=vi)
Điều này cũng áp dụng cho chế độ thao tác bằng cử chỉ, như trong hình 5:
![tràn viền với thao tác bằng cử chỉ](https://developer.android.google.cn/static/images/guide/navigation/e2e-system-bars-bottom.png?authuser=9&hl=vi)
Phần lồng ghép vết cắt trên màn hình
Một số thiết bị có vết cắt trên màn hình. Thông thường, vết cắt nằm ở đầu và được đưa vào thanh trạng thái. Khi màn hình thiết bị ở chế độ ngang thì vết cắt có thể nằm ở cạnh dọc. Tuỳ thuộc vào nội dung mà ứng dụng của bạn hiện trên màn hình, bạn nên triển khai khoảng đệm để tránh vết cắt trên màn hình, vì theo mặc định, các ứng dụng sẽ vẽ ở vết cắt trên màn hình.
Ví dụ: nhiều màn hình ứng dụng cho thấy một danh sách các mục. Không che khuất các mục trong danh sách với vết cắt trên màn hình hoặc thanh hệ thống.
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(binding.recyclerView) { v, insets -> val bars = insets.getInsets( WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() ) v.updatePadding( left = bars.left, top = bars.top, right = bars.right, bottom = bars.bottom, ) WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(mBinding.recyclerView, (v, insets) -> { WindowInsetsCompat bars = insets.getInsets( WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout() ); v.setPadding(bars.left, bars.top, bars.right, bars.bottom); return WindowInsetsCompat.CONSUMED; });
Xác định giá trị của WindowInsetsCompat
bằng cách lấy giá trị logic or của
thanh hệ thống và các loại vết cắt trên màn hình.
Đặt clipToPadding
thành RecyclerView
để khoảng đệm cuộn cùng với
mục trong danh sách. Điều này cho phép các mục ẩn sau thanh hệ thống khi người dùng
như trong ví dụ sau.
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
Phần lồng ghép cử chỉ hệ thống
Các phần lồng ghép cử chỉ hệ thống thể hiện các khu vực cửa sổ nơi các cử chỉ hệ thống ưu tiên hơn ứng dụng của bạn. Những vùng này được thể hiện bằng màu cam trong hình 6:
![Ví dụ về phần lồng ghép cử chỉ hệ thống](https://developer.android.google.cn/static/images/guide/navigation/e2e-system-gesture-insets.png?authuser=9&hl=vi)
Giống như các phần lồng ghép thanh hệ thống, bạn có thể tránh chồng chéo các phần lồng ghép cử chỉ hệ thống
đang sử dụng
getInsets(int)
thông qua tính năng
WindowInsetsCompat.Type.systemGestures()
.
Sử dụng các phần lồng ghép này để di chuyển hoặc thêm các khung hiển thị có thể vuốt ra xa cạnh. Trường hợp sử dụng phổ biến
các trường hợp bao gồm bảng dưới cùng,
vuốt trong trò chơi và băng chuyền được triển khai bằng cách sử dụng
ViewPager2
.
Trên Android 10 trở lên, các phần lồng ghép cử chỉ hệ thống chứa một phần lồng ghép dưới cùng cho cử chỉ màn hình chính và phần lồng ghép bên trái và bên phải cho các cử chỉ quay lại:
![ví dụ về phép đo phần lồng ghép cử chỉ hệ thống](https://developer.android.google.cn/static/images/guide/navigation/e2e-system-gesture-insets-measurements.png?authuser=9&hl=vi)
Ví dụ về mã sau đây cho thấy cách triển khai các phần lồng ghép cử chỉ hệ thống:
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures()) // Apply the insets as padding to the view. Here, set all the dimensions // as appropriate to your layout. You can also update the view's margin if // more appropriate. view.updatePadding(insets.left, insets.top, insets.right, insets.bottom) // Return CONSUMED if you don't want the window insets to keep passing down // to descendant views. WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures()); // Apply the insets as padding to the view. Here, set all the dimensions // as appropriate to your layout. You can also update the view's margin if // more appropriate. view.setPadding(insets.left, insets.top, insets.right, insets.bottom); // Return CONSUMED if you don't want the window insets to keep passing down // to descendant views. return WindowInsetsCompat.CONSUMED; });
Thành phần Material
Thành phần Android Material dựa trên nhiều khung hiển thị
(com.google.android.material){:.external} tự động xử lý các phần lồng ghép, bao gồm
BottomAppBar
!
BottomNavigationView
,
NavigationRailView
và NavigationView
Tuy nhiên, AppBarLayout
không tự động xử lý các phần lồng ghép. Thêm
android:fitsSystemWindows="true"
để xử lý các phần lồng ghép trên cùng hoặc sử dụng setOnApplyWindowInsetsListener
.
Đọc cách xử lý các phần lồng ghép bằng Thành phần Material trong Compose.
Chế độ hiển thị tối đa
Trải nghiệm tốt nhất một số nội dung ở chế độ toàn màn hình, giúp người dùng
một trải nghiệm sống động. Bạn có thể ẩn thanh hệ thống cho chế độ hiển thị tối đa bằng cách sử dụng
WindowInsetsController
và
WindowInsetsControllerCompat
thư viện:
Kotlin
val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) // Hide the system bars. windowInsetsController.hide(Type.systemBars()) // Show the system bars. windowInsetsController.show(Type.systemBars())
Java
Window window = getWindow(); WindowInsetsControllerCompat windowInsetsController = WindowCompat.getInsetsController(window, window.getDecorView()); if (windowInsetsController == null) { return; } // Hide the system bars. windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()); // Show the system bars. windowInsetsController.show(WindowInsetsCompat.Type.systemBars());
Tham khảo bài viết Ẩn thanh hệ thống cho chế độ hiển thị tối đa để biết thêm thông tin về cách triển khai tính năng này.
Tài nguyên khác
Hãy xem các tài liệu tham khảo sau đây để biết thêm thông tin về WindowInsets
, cử chỉ
điều hướng và cách phần lồng ghép hoạt động:
- WindowInsets – trình nghe bố cục
- Thao tác bằng cử chỉ: Phần lồng ghép
- Các phần lồng ghép hoạt động như thế nào trên Android?