Hỗ trợ màn hình đã kết nối

Màn hình được kết nối mở rộng trải nghiệm cửa sổ kiểu máy tính sang điện thoại tiêu chuẩn, giúp người dùng truy cập vào màn hình lớn từ thiết bị di động của họ. Khả năng này mở ra những khả năng mới cho hoạt động tương tác với ứng dụng và năng suất của người dùng.

Tất cả các tính năng riêng biệt của tính năng cửa sổ kiểu máy tính đều áp dụng cho các màn hình đã kết nối. Khi bạn kết nối điện thoại với một màn hình, trạng thái của điện thoại sẽ không thay đổi và một phiên máy tính trống sẽ bắt đầu trên màn hình được kết nối. Thiết bị và màn hình hoạt động như hai hệ thống riêng biệt, với các ứng dụng dành riêng cho từng màn hình.

Hình 1. Điện thoại kết nối với một màn hình ngoài, với một phiên hoạt động trên màn hình ở chế độ máy tính trong khi điện thoại vẫn duy trì trạng thái riêng.

Nếu bạn kết nối một thiết bị có hỗ trợ tính năng cửa sổ kiểu máy tính (chẳng hạn như máy tính bảng) với một màn hình ngoài, thì phiên máy tính sẽ mở rộng trên cả hai màn hình. Sau đó, hai màn hình sẽ hoạt động như một hệ thống liên tục. Chế độ thiết lập này cho phép các cửa sổ, nội dung và con trỏ di chuyển tự do giữa hai màn hình.

Hình 2. Máy tính bảng kết nối với màn hình ngoài, mở rộng phiên làm việc trên máy tính sang cả hai màn hình.

Để hỗ trợ hiệu quả các màn hình được kết nối, bạn cần chú ý đến một số khía cạnh trong thiết kế và quá trình triển khai ứng dụng. Các phương pháp hay nhất sau đây đảm bảo trải nghiệm người dùng diễn ra suôn sẻ và hiệu quả.

Xử lý các thay đổi về màn hình động

Nhiều ứng dụng được tạo ra với giả định rằng đối tượng Display và các đặc điểm của đối tượng này sẽ không thay đổi trong vòng đời của ứng dụng. Tuy nhiên, khi người dùng kết nối hoặc ngắt kết nối một màn hình ngoài, hoặc thậm chí di chuyển cửa sổ ứng dụng giữa các màn hình, đối tượng Display cơ bản được liên kết với ngữ cảnh hoặc cửa sổ của ứng dụng có thể thay đổi. Các thuộc tính của màn hình, chẳng hạn như kích thước, độ phân giải, tốc độ làm mới, khả năng hỗ trợ HDR và mật độ, đều có thể khác nhau. Nếu bạn mã hoá cứng các giá trị dựa trên màn hình điện thoại, ví dụ: bố cục của bạn có thể sẽ bị hỏng trên màn hình ngoài.

Màn hình bên ngoài cũng có thể có mật độ pixel khác nhau. Bạn cần đảm bảo rằng ứng dụng của mình phản hồi chính xác với các thay đổi về mật độ. Điều này bao gồm việc sử dụng pixel không phụ thuộc vào mật độ (dp) cho bố cục, cung cấp các tài nguyên dành riêng cho mật độ và đảm bảo giao diện người dùng của bạn thay đổi kích thước một cách phù hợp.

Nếu một hoạt động đang chạy trên màn hình ngoài khi màn hình đó bị ngắt kết nối, thì hệ thống sẽ di chuyển hoạt động đó sang màn hình chính. Thao tác di chuyển này sẽ kích hoạt các thay đổi về cấu hình (chẳng hạn như thay đổi về kích thước và mật độ màn hình), có thể khiến hoạt động được tạo lại. Ứng dụng của bạn phải xử lý thay đổi cấu hình bằng cách lưu và khôi phục trạng thái giao diện người dùng để tránh mất dữ liệu hoặc trải nghiệm người dùng gây nhầm lẫn.

Sử dụng đúng bối cảnh

Việc sử dụng bối cảnh phù hợp là rất quan trọng trong môi trường nhiều màn hình. Khi truy cập vào tài nguyên, bối cảnh của hoạt động (được hiển thị) khác với bối cảnh của ứng dụng (không được hiển thị).

Bối cảnh của hoạt động chứa thông tin về màn hình và luôn được điều chỉnh cho khu vực hiển thị mà hoạt động đó xuất hiện. Điều này cho phép bạn nhận được thông tin chính xác về mật độ hiển thị hoặc các chỉ số về cửa sổ của ứng dụng. Luôn sử dụng bối cảnh hoạt động (hoặc một bối cảnh dựa trên giao diện người dùng khác) để nhận thông tin về cửa sổ hoặc màn hình hiện tại. Điều này cũng ảnh hưởng đến một số API hệ thống có sử dụng thông tin từ bối cảnh.

Trong Jetpack Compose, bạn có thể truy cập vào thông tin dành riêng cho màn hình bằng cách sử dụng các đối tượng CompositionLocal như LocalConfiguration.currentLocalDensity.current. Khi một hoạt động hoặc cửa sổ di chuyển giữa các màn hình, cấu hình thiết bị sẽ thay đổi, kích hoạt quá trình kết hợp lại với các chỉ số màn hình mới. Các đối tượng CompositionLocal cho phép giao diện người dùng của bạn thích ứng một cách liền mạch.

Nhận thông tin hiển thị

Bạn có thể sử dụng lớp Display để nhận thông tin như kích thước hiển thị, mật độ hoặc cờ. Sử dụng dịch vụ hệ thống DisplayManager để lấy các màn hình có sẵn. Để xác định màn hình ngoài, hãy lọc ra Display.DEFAULT_DISPLAY. Đây thường là màn hình tích hợp của điện thoại hoặc máy tính bảng:

val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val displays = displayManager.getDisplays()
// The default display is 0. External displays have other IDs.
val externalDisplays = displays.filter { it.displayId != Display.DEFAULT_DISPLAY }

Quản lý việc chạy và định cấu hình hoạt động

Với màn hình được kết nối, các ứng dụng có thể chỉ định màn hình mà ứng dụng sẽ chạy khi khởi chạy hoặc khi tạo một hoạt động khác. Hành vi này phụ thuộc vào chế độ chạy của hoạt động được xác định trong tệp kê khai cũng như trên các cờ ý định và tuỳ chọn do thực thể đang khởi chạy hoạt động thiết lập.

Khi một hoạt động chuyển sang màn hình phụ, ứng dụng của bạn có thể phải trải qua quá trình cập nhật bối cảnh, đổi kích thước cửa sổ, cũng như các thay đổi về cấu hình và tài nguyên. Nếu hoạt động xử lý thay đổi về cấu hình, điều này sẽ được thông báo trong onConfigurationChanged(). Nếu không, hoạt động sẽ được khởi chạy lại.

Nếu chế độ chạy đã chọn của một hoạt động cho phép có nhiều thực thể, thì việc khởi chạy trên màn hình phụ có thể tạo ra một thực thể mới của hoạt động đó. Cả hai hoạt động đều được tiếp tục cùng một lúc, điều này có thể hữu ích trong một số trường hợp đa nhiệm.

Bạn có thể chạy một hoạt động trên một màn hình cụ thể bằng cách dùng ActivityOptions. Xin lưu ý rằng launchDisplayId yêu cầu Android 8 (cấp độ API 26) trở lên.

// Get DisplayManager and find the first external display.
val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val externalDisplayId = displayManager.displays
    .firstOrNull { it.displayId != Display.DEFAULT_DISPLAY }
    ?.displayId

// If an external display is found, launch the activity on it.
if (externalDisplayId != null) {
    val intent = Intent(this, MySecondaryActivity::class.java)
    val options = ActivityOptions.makeBasic()
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        options.launchDisplayId = externalDisplayId
    }
    startActivity(intent, options.toBundle())
} else {
    // Optionally, handle the case where no external display is connected.
}

Tránh danh sách cho phép thiết bị

Đôi khi, các ứng dụng hạn chế giao diện người dùng và các tính năng trên màn hình lớn đối với một số thiết bị thông qua danh sách cho phép hoặc bằng cách kiểm tra BUILD.MODEL và kích thước hiển thị tích hợp. Phương pháp này không hiệu quả đối với màn hình được kết nối vì hầu như mọi thiết bị đều có thể kết nối với màn hình lớn và kiểu thiết bị không thay đổi khi màn hình ngoài được kết nối.

Thay vì sử dụng danh sách cho phép hoặc kiểm tra BUILD.MODEL và kích thước hiển thị tích hợp, hãy kiểm tra các chỉ số cửa sổ hoặc khả năng của thiết bị trong thời gian chạy để đưa ra quyết định về giao diện người dùng. Sử dụng API Jetpack WindowManager hoặc các lớp kích thước cửa sổ để tạo bố cục thích ứng và linh hoạt cho nhiều kích thước và mật độ màn hình.

Hỗ trợ thiết bị ngoại vi bên ngoài

Khi kết nối với một màn hình ngoài, người dùng thường tạo ra một môi trường giống như trên máy tính. Việc này thường liên quan đến việc sử dụng bàn phím, chuột, bàn di chuột, webcam, micrô và loa ngoài. Bạn cần đảm bảo ứng dụng của mình hoạt động liền mạch với các thiết bị ngoại vi này. Điều này bao gồm việc xử lý các phím tắt, quản lý các hoạt động tương tác của con trỏ chuột, hỗ trợ đúng cách các camera hoặc micrô bên ngoài và tuân thủ việc định tuyến đầu ra âm thanh. Để biết thêm thông tin, hãy xem bài viết Khả năng tương thích đầu vào trên màn hình lớn.

Nâng cao năng suất của người dùng

Màn hình được kết nối mang đến cơ hội đáng kể để cải thiện năng suất của người dùng. Giờ đây, bạn có các công cụ để tạo ứng dụng di động có thể mang lại trải nghiệm tương đương với các ứng dụng dành cho máy tính. Hãy cân nhắc việc triển khai các tính năng sau để tăng năng suất của người dùng:

  • Cho phép người dùng mở nhiều phiên bản của cùng một ứng dụng. Điều này rất hữu ích cho các tác vụ như so sánh tài liệu, quản lý nhiều cuộc trò chuyện hoặc xem nhiều tệp cùng lúc.
  • Cho phép người dùng chia sẻ dữ liệu đa dạng thức trong và ngoài ứng dụng của bạn bằng tính năng kéo và thả.
  • Giúp người dùng duy trì quy trình làm việc khi có các thay đổi về cấu hình bằng cách triển khai một hệ thống quản lý trạng thái mạnh mẽ.

Bằng cách tuân thủ các nguyên tắc này và sử dụng các ví dụ về mã được cung cấp, bạn có thể tạo các ứng dụng thích ứng liền mạch với màn hình được kết nối, mang đến cho người dùng trải nghiệm phong phú và hiệu quả hơn.