Hỗ trợ vết cắt trên màn hình

Thử cách 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 xử lý vết cắt trên màn hình trong Compose.

Vết cắt trên màn hình là một vùng trên một số thiết bị, mở rộng vào bề mặt màn hình. Thiết kế này mang đến trải nghiệm tràn viền, đồng thời vẫn có không gian cho các cảm biến quan trọng ở mặt trước của thiết bị.

Android hỗ trợ vết cắt trên màn hình trên các thiết bị chạy Android 9 (cấp độ API 28) trở lên. Tuy nhiên, các nhà sản xuất thiết bị cũng có thể hỗ trợ vết cắt trên màn hình trên các thiết bị chạy Android 8.1 trở xuống.

Tài liệu này mô tả cách triển khai tính năng hỗ trợ cho các thiết bị có vết cắt, bao gồm cả cách thao tác với vùng vết cắt, tức là hình chữ nhật tràn viền trên bề mặt hiển thị có chứa vết cắt.

Hình ảnh minh hoạ ví dụ về vết cắt trên màn hình ở giữa trên cùng
Hình 1. 1 Vết cắt trên màn hình.

Chọn cách ứng dụng của bạn xử lý các vùng bị cắt

Nếu bạn không muốn nội dung của mình trùng lặp với một vùng bị cắt, thì bạn chỉ cần đảm bảo nội dung của mình không trùng lặp với thanh trạng thái và thanh điều hướng. Nếu bạn đang kết xuất vào vùng vết cắt, hãy dùng WindowInsetsCompat.getDisplayCutout() để truy xuất một đối tượng DisplayCutout chứa phần lồng ghép an toàn và hộp giới hạn cho từng vết cắt. Các API này cho phép bạn kiểm tra xem nội dung của mình có bị chồng lên phần vết cắt hay không để bạn có thể định vị lại nếu cần.

Bạn cũng có thể xác định xem nội dung có được bố trí phía sau vùng vết cắt hay không. Thuộc tính bố cục cửa sổ layoutInDisplayCutoutMode kiểm soát cách nội dung của bạn được vẽ trong vùng vết cắt. Bạn có thể đặt layoutInDisplayCutoutMode thành một trong các giá trị sau:

  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT: nội dung hiển thị vào vùng vết cắt khi vết cắt trên màn hình nằm trong một thanh hệ thống. Nếu không, cửa sổ sẽ không chồng lên vết cắt trên màn hình; ví dụ: nội dung có thể bị hòm thư khi hiển thị ở chế độ ngang. Nếu ứng dụng của bạn nhắm đến SDK 35, thì điều này được hiểu là ALWAYS đối với các cửa sổ không nổi.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS: nội dung luôn được phép mở rộng vào các vùng vết cắt. Nếu ứng dụng của bạn nhắm đến SDK 35 và đang chạy trên thiết bị Android 15, thì đây là chế độ duy nhất được phép cho các cửa sổ không nổi để đảm bảo màn hình tràn viền.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES: nội dung hiển thị vào vùng vết cắt ở cả chế độ dọc và ngang. Không dùng cho cửa sổ nổi. Nếu ứng dụng của bạn nhắm đến SDK 35, thì điều này được hiểu là ALWAYS đối với các cửa sổ không nổi.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER: nội dung không bao giờ hiển thị vào khu vực vết cắt. Nếu ứng dụng của bạn nhắm đến SDK 35, thì điều này được hiểu là ALWAYS đối với các cửa sổ không nổi.

Bạn có thể đặt chế độ vết cắt theo phương pháp lập trình hoặc bằng cách đặt một kiểu trong hoạt động của mình. Ví dụ sau đây xác định một kiểu để áp dụng thuộc tính LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES cho hoạt động.

<style name="ActivityTheme">
  <item name="android:windowLayoutInDisplayCutoutMode">
    shortEdges <!-- default, shortEdges, or never -->
  </item>
</style>

Các phần sau đây mô tả chi tiết hơn về các chế độ cắt ảnh.

Chế độ mặc định

Nếu ứng dụng của bạn nhắm đến SDK 35 và đang chạy trên thiết bị Android 15, thì LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS là hành vi mặc định và LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT được diễn giải là LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS đối với các cửa sổ không nổi.

Nếu không, LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT là giá trị mặc định.

Hiển thị nội dung trong các khu vực có vết cắt ở cạnh ngắn

Nếu ứng dụng của bạn nhắm đến SDK 35 và đang chạy trên thiết bị Android 15, thì LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES sẽ được diễn giải là LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS cho các cửa sổ không nổi.

Với LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, nội dung sẽ mở rộng vào vùng vết cắt ở cạnh ngắn của màn hình ở cả hướng dọc và hướng ngang, bất kể thanh hệ thống có bị ẩn hay không. Khi sử dụng chế độ này, hãy đảm bảo rằng không có nội dung quan trọng nào trùng lặp với khu vực vết cắt.

Hình ảnh sau đây là ví dụ về LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES cho một thiết bị ở chế độ dọc:

Hình ảnh cho thấy nội dung hiển thị vào khu vực vết cắt khi ở chế độ dọc
Hình 2. Nội dung hiển thị vào vùng vết cắt khi ở chế độ dọc.

Hình ảnh sau đây là ví dụ về LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES cho một thiết bị ở chế độ ngang:

Hình ảnh cho thấy nội dung hiển thị vào khu vực vết cắt khi ở chế độ ngang
Hình 3. Nội dung hiển thị vào khu vực vết cắt khi ở chế độ ngang.

Ở chế độ này, cửa sổ sẽ mở rộng bên dưới vết cắt ở cạnh ngắn của màn hình ở cả hướng dọc và hướng ngang, bất kể cửa sổ có ẩn các thanh hệ thống hay không.

Phần cắt ở góc được coi là nằm ở cạnh ngắn:

Hình ảnh cho thấy một thiết bị có vết cắt ở góc
Hình 4. Thiết bị có vết cắt ở góc.

Không bao giờ hiển thị nội dung trong vùng vết cắt trên màn hình

Nếu ứng dụng của bạn nhắm đến SDK 35 và đang chạy trên thiết bị Android 15, thì LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER sẽ được diễn giải là LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS cho các cửa sổ không nổi.

Với LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER, cửa sổ không bao giờ được phép chồng lên vùng vết cắt.

Sau đây là ví dụ về LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER ở chế độ dọc:

Hình ảnh minh hoạ LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER cho chế độ dọc
Hình 5. Ví dụ về LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER cho chế độ dọc.

Sau đây là ví dụ về LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER ở chế độ ngang:

Hình ảnh minh hoạ LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER cho chế độ ngang
Hình 6. Ví dụ về LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER ở chế độ ngang.

Các phương pháp hay nhất để hỗ trợ vết cắt trên màn hình

Khi xử lý vết cắt trên màn hình, hãy cân nhắc những điều sau:

  • Hãy chú ý đến vị trí của các thành phần quan trọng trong giao diện người dùng. Đừng để vùng bị cắt che khuất bất kỳ văn bản, nút điều khiển hoặc thông tin quan trọng nào.
  • Không đặt hoặc mở rộng bất kỳ phần tử tương tác nào yêu cầu nhận dạng thao tác chạm chính xác vào vùng vết cắt. Độ nhạy cảm ứng có thể thấp hơn ở khu vực có vết cắt.
  • Nếu có thể, hãy dùng WindowInsetsCompat để truy xuất chiều cao của thanh trạng thái và xác định khoảng đệm thích hợp để áp dụng cho nội dung của bạn. Tránh mã hoá cứng chiều cao thanh trạng thái, vì điều này có thể dẫn đến nội dung bị chồng chéo hoặc cắt bớt.

    Hình ảnh minh hoạ nội dung bị cắt ở trên cùng do thiết lập phần lồng ghép không đúng cách
    Hình 7. Sử dụng WindowInsetsCompat để tránh nội dung bị chồng chéo hoặc cắt bớt.
  • Sử dụng View.getLocationInWindow() để xác định lượng không gian cửa sổ mà ứng dụng của bạn đang sử dụng. Đừng giả định rằng ứng dụng đang dùng toàn bộ cửa sổ và đừng dùng View.getLocationOnScreen().

  • Sử dụng chế độ cắt always, shortEdges hoặc never nếu ứng dụng của bạn cần chuyển đổi vào và ra khỏi chế độ hiển thị tối đa. Hành vi mặc định của vết cắt có thể khiến nội dung trong ứng dụng của bạn hiển thị trong vùng vết cắt khi các thanh hệ thống xuất hiện, nhưng không hiển thị ở chế độ hiển thị tối đa. Điều này dẫn đến việc nội dung di chuyển lên và xuống trong quá trình chuyển đổi, như minh hoạ trong ví dụ sau.

    Hình ảnh cho thấy nội dung di chuyển lên và xuống trong quá trình chuyển đổi.
    Hình 8. Ví dụ về nội dung di chuyển lên và xuống trong quá trình chuyển đổi.
  • Ở chế độ sống động, hãy cẩn thận khi sử dụng toạ độ cửa sổ so với toạ độ màn hình, vì ứng dụng của bạn không sử dụng toàn bộ màn hình khi có hiệu ứng hòm thư. Do hiệu ứng hòm thư, toạ độ từ nguồn màn hình không giống với toạ độ từ nguồn cửa sổ. Bạn có thể chuyển đổi toạ độ màn hình thành toạ độ của khung hiển thị khi cần bằng cách sử dụng getLocationOnScreen(). Hình ảnh sau đây cho thấy sự khác biệt về toạ độ khi nội dung được đóng khung:

    Hình ảnh minh hoạ toạ độ cửa sổ so với toạ độ màn hình khi nội dung ở dạng hòm thư.
    Hình 9. Toạ độ cửa sổ so với toạ độ màn hình khi nội dung được đóng khung.
  • Khi xử lý MotionEvent, hãy dùng MotionEvent.getX()MotionEvent.getY() để tránh các vấn đề tương tự về toạ độ. Đừng sử dụng MotionEvent.getRawX() hoặc MotionEvent.getRawY().

Kiểm thử cách nội dung của bạn hiển thị

Kiểm thử tất cả các màn hình và trải nghiệm trong ứng dụng của bạn. Kiểm thử trên các thiết bị có nhiều loại vết cắt, nếu có thể. Nếu không có thiết bị có vết cắt, bạn có thể mô phỏng các cấu hình vết cắt phổ biến trên mọi thiết bị hoặc trình mô phỏng chạy Android 9 trở lên bằng cách làm như sau:

  1. Bật Tuỳ chọn cho nhà phát triển.
  2. Trong màn hình Developer options (Tuỳ chọn cho nhà phát triển), hãy di chuyển xuống phần Drawing (Vẽ) rồi chọn Simulate a display with a cutout (Mô phỏng màn hình có vết cắt).
  3. Chọn loại vết cắt.

    Hình ảnh minh hoạ cách mô phỏng vết cắt trên màn hình trong trình mô phỏng
    Hình 10. Các lựa chọn cho nhà phát triển để kiểm thử cách nội dung của bạn hiển thị.

Tài nguyên khác