Sau khi bạn nhắm đến SDK 35 trở lên trên một thiết bị chạy Android 15 trở lên, ứng dụng của bạn sẽ hiển thị tràn viền. Cửa sổ trải dài toàn bộ chiều rộng và chiều cao của màn hình bằng cách vẽ phía sau các thanh hệ thống. Các thanh hệ thống bao gồm thanh trạng thái, thanh chú thích 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ùng của màn hình và hiển thị phía sau thanh trạng thái. Thanh ứng dụng trên cùng có thể thu nhỏ đến 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 cũng phải kéo dài đến cạnh dưới cùng của màn hình và hiển thị phía sau thanh điều hướng. Nếu không, các ứng dụng phải hiển thị nội dung có thể 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, hãy lưu ý những điều sau:
- Bật chế độ hiển thị tràn viền
- Xử lý mọi trường hợp trùng lặp hình ảnh.
- Hãy cân nhắc việc hiển thị lớp phủ mờ phía sau các thanh hệ thống.

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 bật cho các thiết bị Android 15 trở lên.
Để bật chế độ tràn viền trên các phiên bản Android trước, hãy gọi enableEdgeToEdge
theo cách thủ công trong onCreate
của Activity
.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.enableEdgeToEdge(window)
...
}
Java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowCompat.enableEdgeToEdge(getWindow());
...
}
Theo mặc định, enableEdgeToEdge()
sẽ làm cho các thanh hệ thống trong suốt, ngoại trừ chế độ thao tác bằng 3 nút. Trong chế độ này, thanh trạng thái sẽ có một lớp phủ trong mờ. Màu sắc của các biểu tượng hệ thống và lớp phủ sẽ được điều chỉnh dựa trên giao diện sáng hoặc tối của hệ thống.
Để bật chế độ hiển thị tràn viền trong ứng dụng mà không cần dùng hàm enableEdgeToEdge()
, hãy xem phần Thiết lập chế độ hiển thị tràn viền theo cách thủ công.
Xử lý phần chồng chéo bằ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 tình trạng chồng chéo bằng cách phản ứng với phần lồng ghép. Phần lồng ghép chỉ định những phần nào trên màn hình giao cắt với giao diện người dùng hệ thống, chẳng hạn như thanh điều hướng hoặc thanh trạng thái. Giao nhau có thể có nghĩa là hiển thị phía trên nội dung, nhưng cũng có thể thông báo cho ứng dụng của bạn về các cử chỉ hệ thống.
Các loại phần lồng ghép áp dụng cho việc hiển thị ứng dụng tràn viền là:
Phần lồng ghép thanh hệ thống: phù hợp nhất cho những khung hiển thị có thể nhấn và không được thanh hệ thống che khuất về mặt hình ảnh.
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: cho các vùng điều hướng bằng cử chỉ mà hệ thống sử dụng và có mức độ ưu tiên cao 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 mà giao diện người dùng hệ thống hiển thị theo trục Z phía trên ứng dụng của bạn. Tốt nhất là bạn nên dùng chúng để di chuyển hoặc thêm khoảng đệm cho các khung hiển thị có thể nhấn và không được các thanh hệ thống che khuất về mặt hình ảnh trong ứng dụng của bạn.
Ví dụ: nút hành động nổi (FAB) trong hình 3 bị thanh điều hướng che khuất một phần:

Để tránh tình trạng chồng chéo hình ảnh như vậy ở chế độ thao tác bằng cử chỉ hoặc chế độ nút, bạn có thể tăng lề của khung hiển thị bằng cách sử dụng getInsets(int)
với 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 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 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ụ minh hoạ trong hình 3, thì sẽ không có sự chồng chéo về hình ảnh ở chế độ nút, như minh hoạ trong hình 4:

Điều này cũng áp dụng cho chế độ thao tác bằng cử chỉ, như minh hoạ trong hình 5:

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 màn hình và có trong thanh trạng thái. Khi màn hình thiết bị ở chế độ ngang, 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 thị 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ẽ trong vết cắt trên màn hình.
Ví dụ: nhiều màn hình ứng dụng hiển thị danh sách các mục. Đừng che khuất các mục trong danh sách bằng vết cắt trên màn hình hoặc cá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) -> { Insets 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 or logic của các 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 các mục trong danh sách. Điều này cho phép các mục nằm phía sau thanh hệ thống khi người dùng di chuyển, 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
Phần lồng ghép cử chỉ hệ thống biểu thị các vùng của cửa sổ nơi cử chỉ hệ thống được ưu tiên hơn ứng dụng của bạn. Các vùng này xuất hiện bằng màu cam trong hình 6:

Giống như phần lồng thanh hệ thống, bạn có thể tránh chồng chéo phần lồng cử chỉ hệ thống bằng cách sử dụng getInsets(int)
với WindowInsetsCompat.Type.systemGestures()
.
Hãy dùng các phần lồng ghép này để di chuyển hoặc thêm khoảng đệm cho các khung hiển thị có thể vuốt ra khỏi các cạnh. Các trường hợp sử dụng phổ biến bao gồm trang tính dưới cùng, thao tác vuốt trong trò chơi và băng chuyền được triển khai bằng ViewPager2
.
Trên Android 10 trở lên, 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ỉ trên màn hình chính, cũng như phần lồng ghép bên trái và bên phải cho cử chỉ quay lại:

Ví dụ về mã sau đây cho thấy cách triển khai 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
Nhiều Thành phần Material cho Android dựa trên khung hiển thị (com.google.android.material) sẽ tự động xử lý phần lồng ghép, bao gồm BottomAppBar
, BottomNavigationView
, NavigationRailView
và NavigationView
Tuy nhiên, AppBarLayout
không tự động xử lý phần lồng ghép. Thêm android:fitsSystemWindows="true"
để xử lý phần lồng ghép trên cùng.
Đọc cách xử lý phần lồng ghép bằng Thành phần Material trong Compose.
Khả năng tương thích ngược khi gửi phần lồng ghép
Để ngăn các phần lồng ghép gửi đến các khung hiển thị con và tránh khoảng đệm quá mức, bạn có thể sử dụng các phần lồng ghép bằng hằng số WindowInsetsCompat.CONSUMED
. Tuy nhiên, trên các thiết bị chạy Android 10 (API cấp 29 trở xuống), phần lồng ghép sẽ không được gửi đến các thành phần ngang hàng sau khi gọi WindowInsetsCompat.CONSUMED
, điều này có thể gây ra hiện tượng chồng chéo hình ảnh ngoài ý muốn.

Để xác nhận rằng phần lồng ghép được gửi đến các thành phần ngang hàng cho tất cả các phiên bản Android được hỗ trợ, hãy sử dụng ViewGroupCompat#installCompatInsetsDispatch
trước khi sử dụng phần lồng ghép, có trên AndroidX Core và Core-ktx 1.16.0-alpha01 trở lên.
Kotlin
// Use the i.d. assigned to your layout's root view, e.g. R.id.main val rootView = findViewById(R.id.main) // Call before consuming insets ViewGroupCompat.installCompatInsetsDispatch(rootView)
Java
// Use the i.d. assigned to your layout's root view, e.g. R.id.main LinearLayout rootView = findViewById(R.id.main); // Call before consuming insets ViewGroupCompat.installCompatInsetsDispatch(rootView);

Chế độ hiển thị tối đa
Một số nội dung mang đến trải nghiệm tốt nhất ở chế độ toàn màn hình, giúp người dùng có trải nghiệm phong phú hơn. Bạn có thể ẩn thanh hệ thống cho chế độ hiển thị tối đa bằng cách sử dụng các thư viện WindowInsetsController
và WindowInsetsControllerCompat
:
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());
Hãy 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.
Biểu tượng thanh hệ thống
Việc gọi enableEdgeToEdge
đảm bảo màu biểu tượng thanh hệ thống sẽ cập nhật khi giao diện thiết bị thay đổi.
Khi chuyển sang chế độ tràn viền, bạn có thể cần cập nhật màu biểu tượng thanh hệ thống theo cách thủ công để chúng tương phản với nền của ứng dụng. Ví dụ: để tạo biểu tượng thanh trạng thái sáng:
Kotlin
WindowCompat.getInsetsController(window, window.decorView) .isAppearanceLightStatusBars = false
Java
WindowCompat.getInsetsController(window, window.getDecorView()) .setAppearanceLightStatusBars(false);
Bảo vệ thanh hệ thống
Sau khi ứng dụng của bạn nhắm đến SDK 35 trở lên, chế độ hiển thị tràn viền sẽ được thực thi.
Thanh trạng thái hệ thống và thanh thao tác bằng cử chỉ có màu trong suốt, nhưng thanh thao tác bằng 3 nút có màu trong mờ. Gọi enableEdgeToEdge
để đặt chế độ tương thích ngược.
Tuy nhiên, chế độ mặc định của hệ thống có thể không phù hợp với mọi trường hợp sử dụng. Tham khảo hướng dẫn thiết kế thanh hệ thống của Android và Thiết kế tràn viền để xác định xem có nên sử dụng thanh hệ thống trong suốt hay mờ hay không.
Tạo thanh hệ thống trong suốt
Tạo một thanh trạng thái trong suốt bằng cách nhắm đến Android 15 (SDK 35) trở lên hoặc bằng cách gọi enableEdgeToEdge()
với các đối số mặc định cho các phiên bản trước đó.
Tạo một thanh điều hướng bằng cử chỉ trong suốt bằng cách nhắm đến Android 15 trở lên hoặc bằng cách gọi enableEdgeToEdge()
với các đối số mặc định cho các phiên bản trước. Đối với thanh thao tác bằng 3 nút, hãy đặt Window.setNavigationBarContrastEnforced
thành false
, nếu không sẽ có một lớp phủ mờ được áp dụng.
Tạo các thanh hệ thống trong mờ
Để tạo một thanh trạng thái trong suốt, hãy làm như sau:
- Cập nhật phần phụ thuộc
androidx-core
lên 1.16.0-beta01 trở lên - Bao bố cục XML của bạn trong
androidx.core.view.insets.ProtectionLayout
và chỉ định một mã nhận dạng. - Truy cập vào
ProtectionLayout
theo phương thức lập trình để thiết lập các biện pháp bảo vệ, chỉ định phía vàGradientProtection
cho thanh trạng thái.
<androidx.core.view.insets.ProtectionLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list_protection" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:id="@+id/item_list" android:clipToPadding="false" android:layout_width="match_parent" android:layout_height="match_parent"> <!--items--> </ScrollView> </androidx.core.view.insets.ProtectionLayout>
findViewById<ProtectionLayout>(R.id.list_protection) .setProtections( listOf( GradientProtection( WindowInsetsCompat.Side.TOP, // Ideally, this is the pane's background color paneBackgroundColor ) ) )
Đảm bảo ColorInt
được truyền vào GradientProtection
khớp với nền nội dung. Ví dụ: bố cục chi tiết danh sách hiển thị trên một thiết bị có thể gập lại có thể có GradientProtections
khác nhau với các màu khác nhau cho bảng danh sách và bảng chi tiết.
Không tạo thanh thao tác bằng cử chỉ mờ. Để tạo một thanh điều hướng gồm 3 nút mờ, hãy làm một trong những việc sau:
- Nếu đã có bố cục được bao bọc trong một
ProtectionView
, bạn có thể truyền thêm mộtColorProtection
hoặcGradientProtection
vào phương thứcsetProtections
. Trước khi thực hiện, hãy đảm bảowindow.isNavigationBarContrastEnforced = false
. - Nếu không, hãy đặt
window.isNavigationBarContrastEnforced = true
. Nếu ứng dụng của bạn gọienableEdgeToEdge, window.isNavigationBarContrastEnforced = true
thì đó là giá trị mặc định.
Các mẹo khác
Các mẹo khác khi xử lý phần lồng ghép.
Hiển thị nội dung có thể cuộn tràn viền
Kiểm tra để đảm bảo mục cuối cùng trong danh sách không bị các thanh hệ thống che khuất trong RecyclerView
hoặc NestedScrollView
bằng cách xử lý phần lồng ghép và đặt clipToPadding
thành false
.
Video sau đây cho thấy một RecyclerView
có màn hình tràn viền ở trạng thái tắt (bên trái) và bật (bên phải):
Hãy xem các đoạn mã trong phần Tạo danh sách động bằng RecyclerView để biết mã mẫu.
Chuyển hộp thoại toàn màn hình sang chế độ tràn viền
Để hộp thoại toàn màn hình hiển thị tràn viền, hãy gọi enableEdgeToEdge
trên Dialog.
Kotlin
class MyAlertDialogFragment : DialogFragment() {
override fun onStart(){
super.onStart()
dialog?.window?.let { WindowCompat.enableEdgeToEdge(it) }
}
...
}
Java
public class MyAlertDialogFragment extends DialogFragment {
@Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
Window window = dialog.getWindow();
if (window != null) {
WindowCompat.enableEdgeToEdge(window);
}
}
}
...
}
Tài nguyên khác
Hãy xem các tài liệu tham khảo sau để biết thêm thông tin về việc hiển thị tràn viền.
Blog
- Các mẹo xử lý phần lồng ghép cho biện pháp thực thi chế độ tràn viền của Android 15
- WindowInsets – trình nghe bố cục
Thiết kế
Tài liệu khác
Video