Hiển thị nội dung tràn viền trong ứng dụng của bạn

Thử cách sử dụng Compose
Jetpack Compose là bộ công cụ giao diện người dùng được đề xuất cho Android. Tìm hiểu cách làm việc với công cụ tràn viền trong Compose.

Bạn có thể làm cho ứng dụng hiển thị hiện nội dung tràn viền (sử dụng 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 thanh hệ thống. Thanh hệ thống là thanh trạng thái và thanh điều hướng.

Để triển khai bố cục tràn viền, ứng dụng của bạn phải làm như sau:

  • Vẽ phía sau thanh điều hướng để đạt được trải nghiệm người dùng hấp dẫn và hiện đại hơn.
  • Vẽ phía sau thanh trạng thái nếu thanh trạng thái phù hợp với nội dung và bố cục của bạn, chẳng hạn như trong trường hợp hình ảnh có chiều rộng đầy đủ. Để thực hiện việc này, hãy dùng các API như AppBarLayout, nhằm xác định thanh ứng dụng được ghim vào đầu màn hình.
Hình 1. Các thanh hệ thống trong bố cục tràn viền.

Để triển khai bố cục tràn viền trong ứng dụng, hãy thực hiện các bước sau:

  1. Bật màn hình tràn viền.
  2. Xử lý mọi trường hợp trùng lặp hình ảnh.
Hình ảnh một ứng dụng kèm theo hình ảnh phía sau thanh trạng thái
Hình 2. Ví dụ về ứng dụng có hình ảnh phía sau thanh trạng thái.

Bật màn hình tràn viền.

Bạn có thể bật màn hình tràn viền trong ứng dụng bằng cách gọi enableEdgeToEdge trong onCreate của Activity. Phương thức này sẽ đượ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 làm cho các thanh hệ thống trong suốt, ngoại trừ ở chế độ điều hướng bằng 3 nút, trong đó thanh trạng thái sẽ có màn hình trong suốt. Màu của các biểu tượng hệ thống và màn hình được điều chỉnh dựa trên giao diện sáng hoặc tối của hệ thống.

Phương thức enableEdgeToEdge sẽ tự động khai báo rằng ứng dụng nên được đặt cạnh nhau và điều chỉnh màu của các thanh hệ thống. Hãy xem phần "Thiết lập màn hình tràn viền theo cách thủ công" nếu việc này là cần thiết vì bất kỳ lý do gì.

Xử lý các trường hợp trùng lặp bằng cách sử dụng phần lồng ghép

Sau khi bạn bật màn hình tràn viền, 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 trường hợp trùng lặp bằng cách phản ứng với phần lồng ghép, chỉ định những phần của màn hình giao nhau 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. Việc giao cắt 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 về các cử chỉ của hệ thống.

Các loại phần lồng ghép áp dụng để 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 với những khung hiển thị có thể nhấn vào và không bị thanh hệ thống che khuất hình ảnh.

  • 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 và đượ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 mà giao diện người dùng hệ thống hiển thị trong trục Z phía trên ứng dụng của bạn. Bạn nên sử dụng giao diện này để di chuyển hoặc đệm các khung hiển thị có thể nhấn vào trong ứng dụng và không bị che khuất hình ảnh bởi các thanh hệ thống.

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:

Hình ảnh minh hoạ cách triển khai tràn viền, nhưng thanh điều hướng che phủ FAB
Hình 3. Thanh điều hướng chồng lên FAB trong bố cục tràn viền.

Để 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 khung hiển thị bằng cách sử dụng getInsets(int) thông qua WindowInsetsCompat.Type.systemBars().

Ví dụ về mã sau đây cho thấy cách triển khai các 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ụ minh hoạ trong hình 3, thì sẽ không có tình trạng trùng lặp hình ảnh ở chế độ nút, như minh hoạ trong hình 4:

Hình ảnh thanh điều hướng mờ không che phủ FAB
Hình 4. Giải quyết tình trạng chồng chéo hình ảnh ở chế độ nút.

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

Hình ảnh hiển thị tràn viền trong thao tác bằng cử chỉ
Hình 5. Giải quyết tình trạng trùng lặp hình ảnh ở chế độ thao tác bằng cử chỉ.

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 cửa sổ nơi các cử chỉ hệ thống sẽ được ưu tiên hơn ứng dụng của bạn. Những vùng này được hiển thị bằng màu cam trong hình 6:

Hình ảnh thể hiện các phần lồng ghép cử chỉ hệ thống
Hình 6. Phần lồng ghép cử chỉ hệ thống.

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 bằng cách sử dụng getInsets(int) với WindowInsetsCompat.Type.systemGestures().

Sử dụng các phần lồng ghép này để di chuyển hoặc di chuyển các chế độ xem có thể vuốt ra khỏi các cạnh. Một số trường hợp sử dụng phổ biến 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 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à một phần lồng ghép bên trái và bên phải cho cử chỉ quay lại:

Hình ảnh minh hoạ các phép đo phần lồng ghép cử chỉ hệ thống
Hình 7. Đo lường phần lồng ghép cử chỉ hệ thống.

Mã ví dụ 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;
});

Chế độ hiển thị tối đa

Một số nội dung có trải nghiệm tốt nhất ở chế độ toàn màn hình, mang đến cho người dùng trải nghiệm sống động hơn. Bạn có thể ẩn các thanh hệ thống cho chế độ hiển thị tối đa bằng cách sử dụng thư viện WindowInsetsControllerWindowInsetsControllerCompat:

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 để biết thêm thông tin về WindowInsets, thao tác bằng cử chỉ và cách hoạt động của phần lồng ghép: