Việc mở rộng từ điện thoại sang nhiều kiểu dáng màn hình lớn sẽ đặt ra những điểm cần cân nhắc về cách trò chơi của bạn xử lý việc quản lý cửa sổ. Trên Googlebook, ChromeOS và Google Play Games trên máy tính, trò chơi của bạn có thể chạy ở chế độ cửa sổ trên giao diện máy tính chính. Trên các máy tính bảng và thiết bị có thể gập lại mới của Android chạy Android 12L (API cấp 32) trở lên có chiều rộng màn hình > 600 dp, trò chơi của bạn có thể chạy song song ở chế độ chia đôi màn hình với các ứng dụng khác, được đổi kích thước và thậm chí được di chuyển giữa màn hình trong và ngoài trên thiết bị có thể gập lại, dẫn đến thay đổi về cấu hình cho kích thước cửa sổ và hướng (trên một số thiết bị).
Khả năng thay đổi kích thước với trò chơi Unity
Cấu hình màn hình lớn cơ bản
Khai báo xem trò chơi của bạn có thể xử lý tính năng thay đổi kích thước hay không:
<android:resizeableActivity="true" or "false" />
Nếu không hỗ trợ tính năng thay đổi kích thước, hãy đảm bảo tệp kê khai trò chơi xác định rõ ràng tỷ lệ khung hình tối thiểu và tối đa được hỗ trợ:
<!-- Render full screen between 3:2 and 21:9 aspect ratio -->
<!-- Let the platform letterbox otherwise -->
<activity android:minAspectRatio="1.5">
<activity android:maxAspectRatio="2.33">
Google Play Games trên máy tính
Đối với Google Play Games trên máy tính, nền tảng này xử lý khả năng thay đổi kích thước cửa sổ trong khi vẫn tuân thủ tỷ lệ khung hình đã chỉ định. Kích thước cửa sổ được tự động khoá theo kích thước tối ưu. Bạn cần hỗ trợ ít nhất tỷ lệ khung hình 16:9 nếu hướng chính là hướng ngang và tỷ lệ khung hình 9:16 nếu trò chơi của bạn ở chế độ dọc. Để mang lại trải nghiệm tốt nhất, hãy hỗ trợ rõ ràng tỷ lệ khung hình 21:9, 16:10 và 3:2 cho trò chơi ở chế độ ngang. Khả năng thay đổi kích thước cửa sổ không bắt buộc ở đây nhưng vẫn nên có để tương thích với các kiểu dáng khác.
Để biết thêm thông tin và các phương pháp hay nhất, hãy xem bài viết Định cấu hình đồ hoạ cho Google Play Games trên máy tính.
Màn hình lớn
Để tối đa hoá vùng có thể xem cho trò chơi ở chế độ toàn màn hình trên máy tính bảng màn hình lớn, thiết bị có thể gập lại, Googlebook, ChromeOS và màn hình được kết nối, hãy hỗ trợ chế độ chìm toàn màn hình và ẩn các thanh hệ thống bằng cách đặt cờ trên decorView, chế độ hiển thị giao diện người dùng hệ thống hoặc thông qua API WindowInsetsCompat. Bạn cũng nên xử lý các sự kiện xoay và thay đổi kích thước cấu hình một cách thích hợp hoặc ngăn chúng xảy ra.
Xin lưu ý rằng trên các thiết bị Android có màn hình lớn, trò chơi của bạn có thể chạy ở những cấu hình mà bạn có thể chưa xử lý. Nếu trò chơi của bạn không hỗ trợ tất cả các cấu hình về kích thước cửa sổ và hướng, thì nền tảng sẽ chèn viền đen vào trò chơi của bạn ở chế độ tương thích và nếu cần, sẽ nhắc người chơi trước khi chuyển sang một cấu hình không được hỗ trợ.
Trên một số thiết bị, khi người chơi chuyển sang một cấu hình không được hỗ trợ, họ có thể thấy lời nhắc về lựa chọn tải lại trò chơi và tạo lại hoạt động để phù hợp nhất với bố cục cửa sổ mới. Điều này làm gián đoạn trải nghiệm chơi. Kiểm thử trò chơi của bạn trong nhiều cấu hình chế độ nhiều cửa sổ (kích thước cửa sổ 2/3, 1/2, 1/3) và xác minh rằng không có yếu tố nào trong lối chơi hoặc giao diện người dùng bị cắt hoặc không truy cập được. Ngoài ra, hãy kiểm thử cách trò chơi của bạn phản hồi tính năng tiếp tục trên thiết bị có thể gập lại khi di chuyển giữa màn hình trong và màn hình ngoài trên các thiết bị này. Nếu bạn gặp vấn đề, hãy xử lý rõ ràng các sự kiện cấu hình này và thêm tính năng hỗ trợ thay đổi kích thước nâng cao cho màn hình lớn.
Khả năng thay đổi kích thước nâng cao trên màn hình lớn
Để thoát khỏi chế độ tương thích và tránh tạo lại hoạt động, hãy làm như sau:
Khai báo hoạt động chính của bạn là có thể thay đổi kích thước:
<android:resizeableActivity="true" />Khai báo sự hỗ trợ rõ ràng cho "orientation", "screenSize", "smallestScreenSize", "screenLayout" và "density" trong thuộc tính
android:configChangescủa phần tử<activity>trong tệp kê khai trò chơi để nhận tất cả các sự kiện về cấu hình màn hình lớn:<android:configChanges="screenSize | smallestScreenSize | screenLayout | orientation | keyboard | keyboardHidden | density" />Ghi đè
onConfigurationChanged()và xử lý sự kiện cấu hình, bao gồm cả hướng hiện tại, kích thước cửa sổ, chiều rộng và chiều cao:Kotlin
override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) val density: Float = resources.displayMetrics.density val newScreenWidthPixels = (newConfig.screenWidthDp * density).toInt() val newScreenHeightPixels = (newConfig.screenHeightDp * density).toInt() // Configuration.ORIENTATION_PORTRAIT or ORIENTATION_LANDSCAPE val newScreenOrientation: Int = newConfig.orientation // ROTATION_0, ROTATION_90, ROTATION_180, or ROTATION_270 val newScreenRotation: Int = windowManager.defaultDisplay.rotation }
Java
@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); float density = getResources().getDisplayMetrics().density; int newScreenWidthPixels = (int) (newConfig.screenWidthDp * density); int newScreenHeightPixels = (int) (newConfig.screenHeightDp * density); // Configuration.ORIENTATION_PORTRAIT or ORIENTATION_LANDSCAPE int newScreenOrientation = newConfig.orientation; // ROTATION_0, ROTATION_90, ROTATION_180, or ROTATION_270 int newScreenRotation = getWindowManager().getDefaultDisplay() .getRotation(); }
Bạn cũng có thể truy vấn WindowManager để kiểm tra hướng xoay hiện tại của thiết bị. Dựa vào siêu dữ liệu này, hãy kiểm tra kích thước cửa sổ mới và kết xuất theo kích thước cửa sổ đầy đủ. Cách này có thể không hiệu quả trong một số trường hợp do sự khác biệt về tỷ lệ khung hình. Vì vậy, bạn có thể chọn cách khác là cố định giao diện người dùng của trò chơi theo kích thước cửa sổ mới và tạo hiệu ứng hòm thư cho nội dung cốt lõi của trò chơi. Nếu có những hạn chế về kỹ thuật hoặc thiết kế khiến bạn không thể sử dụng một trong hai phương pháp này, hãy tự tạo hiệu ứng hòm thư trong công cụ để giữ nguyên tỷ lệ khung hình và điều chỉnh tỷ lệ theo kích thước phù hợp nhất có thể trong khi khai báo resizeableActivity = false và tránh chế độ cấu hình.
Bất kể bạn chọn cách tiếp cận nào, hãy kiểm thử trò chơi của bạn trong nhiều cấu hình (gập và mở, các thay đổi về hướng xoay, chế độ chia đôi màn hình) và đảm bảo không có thành phần giao diện người dùng nào trong trò chơi bị cắt hoặc chồng chéo, không có vấn đề nào về khả năng tiếp cận mục tiêu cảm ứng hoặc vấn đề về tỷ lệ khung hình khiến trò chơi bị kéo giãn, bóp méo hoặc biến dạng.
Ngoài ra, màn hình lớn hơn thường có nghĩa là pixel lớn hơn, vì bạn có cùng số lượng pixel cho một vùng lớn hơn nhiều. Điều này có thể gây ra hiện tượng vỡ hình cho các vùng đệm kết xuất được giảm kích thước hoặc các thành phần có độ phân giải thấp. Sử dụng những thành phần có chất lượng cao nhất trên các thiết bị có màn hình lớn và lập hồ sơ hiệu suất cho trò chơi để đảm bảo không có vấn đề gì. Nếu trò chơi của bạn hỗ trợ nhiều cấp độ chất lượng, hãy đảm bảo rằng trò chơi có tính đến các thiết bị có màn hình lớn.
Chế độ nhiều cửa sổ
Chế độ nhiều cửa sổ cho phép nhiều ứng dụng đồng thời chia sẻ cùng một màn hình. Chế độ nhiều cửa sổ không thay đổi vòng đời của activity; tuy nhiên, trạng thái tiếp tục của các ứng dụng trong chế độ nhiều cửa sổ sẽ thay đổi theo các phiên bản Android khác nhau (xem phần Vòng đời của activity ở chế độ nhiều cửa sổ trong phần Hỗ trợ chế độ nhiều cửa sổ).
Khi người chơi đặt một ứng dụng hoặc trò chơi ở chế độ nhiều cửa sổ, hệ thống sẽ thông báo cho hoạt động về sự thay đổi cấu hình như được chỉ định trong phần Khả năng thay đổi kích thước nâng cao trên màn hình lớn. Việc thay đổi cấu hình cũng xảy ra khi người chơi đổi kích thước trò chơi hoặc đưa trò chơi trở về chế độ toàn màn hình.
Không có gì đảm bảo rằng ứng dụng sẽ lấy lại tiêu điểm khi được đặt ở chế độ nhiều cửa sổ. Do đó, nếu bạn dùng bất kỳ sự kiện trạng thái ứng dụng nào để tạm dừng trò chơi, thì đừng dựa vào sự kiện lấy tiêu điểm (onWindowFocusChanged() với giá trị tiêu điểm là true) để tiếp tục trò chơi. Thay vào đó, hãy sử dụng các trình xử lý sự kiện hoặc trình xử lý thay đổi trạng thái khác, chẳng hạn như onConfigurationChanged() hoặc onResume(). Xin lưu ý rằng bạn luôn có thể sử dụng phương thức isInMultiWindowMode() để phát hiện xem hoạt động hiện tại có đang chạy ở chế độ nhiều cửa sổ hay không.
Khi sử dụng chế độ cửa sổ trên máy tính cho Googlebook, ChromeOS, máy tính bảng và thiết bị có thể gập lại có màn hình lớn, kích thước cửa sổ ban đầu là một yếu tố quan trọng cần cân nhắc. Trò chơi không cần phải ở chế độ toàn màn hình và bạn sẽ muốn khai báo kích thước cửa sổ trong trường hợp đó. Có 2 cách được đề xuất để thực hiện việc này.
Lựa chọn đầu tiên hoạt động bằng cách sử dụng các thuộc tính cụ thể trên thẻ <layout> trong tệp kê khai Android. Các thuộc tính defaultHeight và defaultWidth kiểm soát các phương diện ban đầu. Hãy lưu ý đến các thuộc tính minHeight và minWidth để ngăn người chơi thay đổi kích thước cửa sổ trò chơi thành những kích thước mà bạn không hỗ trợ. Cuối cùng là thuộc tính gravity. Thuộc tính này xác định vị trí trên màn hình mà cửa sổ sẽ xuất hiện khi khởi chạy. Sau đây là ví dụ về thẻ bố cục sử dụng các thuộc tính này:
<layout android:defaultHeight="500dp"
android:defaultWidth="600dp"
android:gravity="top|end"
android:minHeight="450dp"
android:minWidth="300dp" />
Lựa chọn thứ hai để đặt kích thước cửa sổ là sử dụng ranh giới khởi chạy động. Bằng cách sử dụng setLaunchBounds(Rect), bạn có thể xác định kích thước cửa sổ ban đầu. Nếu bạn chỉ định một hình chữ nhật trống, thì hoạt động sẽ bắt đầu ở trạng thái tối đa hoá.
Ngoài ra, nếu bạn đang sử dụng công cụ phát triển trò chơi Unity hoặc Unreal, hãy đảm bảo rằng bạn đang sử dụng một phiên bản gần đây (Unity 2019.4.40 và Unreal 5.3 trở lên) có khả năng hỗ trợ tốt cho chế độ nhiều cửa sổ.
Hỗ trợ tư thế có thể gập lại
Sử dụng thư viện bố cục WindowManager của Jetpack để hỗ trợ các tư thế thiết bị gập, chẳng hạn như tư thế đặt trên mặt bàn, nhằm tăng mức độ đắm chìm và mức độ gắn bó của người chơi:
Kotlin
fun isTableTopPosture(foldFeature : FoldingFeature?) : Boolean { contract { returns(true) implies (foldFeature != null) } return foldFeature?.state == FoldingFeature.State.HALF_OPENED && foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL }
Java
boolean isTableTopPosture(FoldingFeature foldFeature) { return (foldFeature != null) && (foldFeature.getState() == FoldingFeature.State.HALF_OPENED) && (foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL); }