แอปของคุณทำงานได้ดีในโทรศัพท์ที่อยู่ในแนวนอน คุณจึงจำกัด แอปให้แสดงในแนวนอนเท่านั้น แต่คุณเห็นโอกาสที่จะทำสิ่งต่างๆ ได้มากขึ้นบนหน้าจอขนาดใหญ่ใน แนวนอน
คุณจะทำอย่างไรหากต้องการจำกัดแอปให้แสดงในแนวนอนบนหน้าจอขนาดเล็ก แต่เปิดใช้แนวนอนบนหน้าจอขนาดใหญ่
คำแนะนำนี้เป็นมาตรการชั่วคราวจนกว่าคุณจะปรับปรุงแอปให้รองรับการกำหนดค่าอุปกรณ์ทั้งหมดได้อย่างเต็มรูปแบบ
ผลลัพธ์
แอปจะยังคงอยู่ในแนวตั้งบนหน้าจอขนาดเล็กไม่ว่าจะหมุนอุปกรณ์อย่างไรก็ตาม ในหน้าจอขนาดใหญ่ แอปจะรองรับการวางแนวแนวนอนและแนวตั้ง
ความเข้ากันได้ของเวอร์ชัน
การติดตั้งใช้งานนี้ใช้ได้กับ API ทุกระดับ
การขึ้นต่อกัน
Kotlin
implementation("androidx.window:window:1.5.1")
implementation("androidx.window:window-core:1.5.1")
Groovy
implementation "androidx.window:window:1.5.1"
implementation "androidx.window:window-core:1.5.1"
จัดการการวางแนวของแอป
หากต้องการเปิดใช้การวางแนวแนวนอนบนหน้าจอขนาดใหญ่ ให้ตั้งค่าไฟล์ Manifest ของแอปเพื่อ จัดการการเปลี่ยนแปลงการวางแนวโดยค่าเริ่มต้น กำหนดขนาดหน้าต่างแอป ที่รันไทม์ หากหน้าต่างแอปมีขนาดเล็ก ให้จำกัดการวางแนวของแอปโดยการลบล้าง การตั้งค่าการวางแนวในไฟล์ Manifest
1. ระบุการตั้งค่าการวางแนวในไฟล์ Manifest ของแอป
คุณสามารถหลีกเลี่ยงการประกาศองค์ประกอบ screenOrientation ของไฟล์
Manifest ของแอป (ในกรณีนี้ การวางแนวจะเป็นค่าเริ่มต้นเป็น unspecified) หรือตั้งค่าการวางแนวหน้าจอเป็น fullUser หากผู้ใช้ไม่ได้ล็อกการหมุนตามเซ็นเซอร์
แอปของคุณจะรองรับการวางแนวอุปกรณ์ทั้งหมด
<activity
android:name=".MyActivity"
android:screenOrientation="fullUser">
ความแตกต่างระหว่าง unspecified กับ fullUser อาจดูเล็กน้อยแต่มีความสำคัญ หากคุณไม่ประกาศค่า screenOrientation ระบบจะเลือกการวางแนว และนโยบายที่ระบบใช้เพื่อกำหนดการวางแนวอาจแตกต่างกันไปในแต่ละอุปกรณ์ ในทางกลับกัน การระบุ fullUser จะตรงกับลักษณะการทำงานที่ผู้ใช้กำหนดไว้สำหรับอุปกรณ์มากกว่า กล่าวคือ หากผู้ใช้ล็อกการหมุนตามเซ็นเซอร์ แอปจะทำตามค่ากำหนดของผู้ใช้ ไม่เช่นนั้น ระบบจะอนุญาตการวางแนวหน้าจอที่เป็นไปได้ทั้ง 4 แบบ (แนวตั้ง แนวนอน แนวตั้งกลับด้าน หรือแนวนอนกลับด้าน) ดู screenOrientation
2. กำหนดขนาดหน้าจอ
เมื่อตั้งค่าไฟล์ Manifest ให้รองรับการวางแนวทั้งหมดที่ผู้ใช้ได้รับอนุญาตแล้ว คุณจะ ระบุการวางแนวแอปแบบเป็นโปรแกรมตามขนาดหน้าจอได้
เพิ่มไลบรารี Jetpack WindowManager ลงในไฟล์ build.gradle หรือ
build.gradle.kts ของโมดูล
Kotlin
implementation("androidx.window:window:version") implementation("androidx.window:window-core:version")
Groovy
implementation 'androidx.window:window:version' implementation 'androidx.window:window-core:version'
ใช้เมธอด Jetpack WindowManager
WindowMetricsCalculator#computeMaximumWindowMetrics() เพื่อรับ
ขนาดหน้าจออุปกรณ์เป็นออบเจ็กต์ WindowMetrics คุณสามารถ
เปรียบเทียบเมตริกหน้าต่างกับคลาสขนาดหน้าต่างเพื่อตัดสินใจว่าจะจำกัดการวางแนวเมื่อใด
คลาสขนาดหน้าต่างจะระบุเบรกพอยต์ระหว่างหน้าจอขนาดเล็กและขนาดใหญ่
ใช้จุดพัก WindowWidthSizeClass#COMPACT และ WindowHeightSizeClass#COMPACT เพื่อกำหนดขนาดหน้าจอ
Kotlin
/** Determines whether the device has a compact screen. **/
fun compactScreen() : Boolean {
val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this)
val width = metrics.bounds.width()
val height = metrics.bounds.height()
val density = resources.displayMetrics.density
val windowSizeClass = WindowSizeClass.compute(width/density, height/density)
return windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT ||
windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT
}
Java
/** Determines whether the device has a compact screen. **/
private boolean compactScreen() {
WindowMetrics metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this);
int width = metrics.getBounds().width();
int height = metrics.getBounds().height();
float density = getResources().getDisplayMetrics().density;
WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density);
return windowSizeClass.getWindowWidthSizeClass() == WindowWidthSizeClass.COMPACT ||
windowSizeClass.getWindowHeightSizeClass() == WindowHeightSizeClass.COMPACT;
}
- หมายเหตุ:
- ตัวอย่างจะได้รับการติดตั้งใช้งานเป็นเมธอดของกิจกรรม ดังนั้นระบบจึงยกเลิกการอ้างอิงกิจกรรมเป็น
thisในอาร์กิวเมนต์ของcomputeMaximumWindowMetrics() - เราใช้วิธี
computeMaximumWindowMetrics()แทนcomputeCurrentWindowMetrics()เนื่องจากสามารถเปิดแอปในโหมดหลายหน้าต่างได้ ซึ่งจะไม่สนใจการตั้งค่าการวางแนวหน้าจอ ไม่มีเหตุผลที่จะกำหนดขนาดหน้าต่างแอปและลบล้างการตั้งค่าการวางแนว เว้นแต่หน้าต่างแอปจะเป็นทั้งหน้าจอของอุปกรณ์
ดูWindowManager เพื่อดูวิธีการประกาศการอ้างอิงเพื่อให้เมธอด
computeMaximumWindowMetrics() พร้อมใช้งานในแอป
3. ลบล้างการตั้งค่าไฟล์ Manifest ของแอป
เมื่อพิจารณาแล้วว่าอุปกรณ์มีขนาดหน้าจอแบบกะทัดรัด คุณสามารถเรียกใช้
Activity#setRequestedOrientation() เพื่อลบล้างการตั้งค่า
screenOrientation ของไฟล์ Manifest ได้
Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestedOrientation = if (compactScreen())
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
ActivityInfo.SCREEN_ORIENTATION_FULL_USER
...
// Replace with a known container that you can safely add a
// view to where the view won't affect the layout and the view
// won't be replaced.
val container: ViewGroup = binding.container
// Add a utility view to the container to hook into
// View.onConfigurationChanged. This is required for all
// activities, even those that don't handle configuration
// changes. You can't use Activity.onConfigurationChanged,
// since there are situations where that won't be called when
// the configuration changes. View.onConfigurationChanged is
// called in those scenarios.
container.addView(object : View(this) {
override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
requestedOrientation = if (compactScreen())
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
ActivityInfo.SCREEN_ORIENTATION_FULL_USER
}
})
}
Java
@Override
protected void onCreate(Bundle savedInstance) {
super.onCreate(savedInstanceState);
if (compactScreen()) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
}
...
// Replace with a known container that you can safely add a
// view to where the view won't affect the layout and the view
// won't be replaced.
ViewGroup container = binding.container;
// Add a utility view to the container to hook into
// View.onConfigurationChanged. This is required for all
// activities, even those that don't handle configuration
// changes. You can't use Activity.onConfigurationChanged,
// since there are situations where that won't be called when
// the configuration changes. View.onConfigurationChanged is
// called in those scenarios.
container.addView(new View(this) {
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (compactScreen()) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
}
}
});
}
การเพิ่มตรรกะลงในเมธอด onCreate() และ View.onConfigurationChanged()
จะช่วยให้คุณได้รับเมตริกหน้าต่างสูงสุดและลบล้างการตั้งค่า
การวางแนวได้ทุกเมื่อที่มีการปรับขนาดหรือย้ายกิจกรรมระหว่างจอแสดงผล
เช่น หลังจากหมุนอุปกรณ์ หรือเมื่อพับหรือกางอุปกรณ์แบบพับได้
ดูข้อมูลเพิ่มเติมเกี่ยวกับเวลาที่การเปลี่ยนแปลงการกำหนดค่าเกิดขึ้นและเวลาที่การเปลี่ยนแปลงดังกล่าวทำให้เกิดการสร้างกิจกรรมใหม่ได้ที่จัดการการเปลี่ยนแปลงการกำหนดค่า
ข้อมูลสำคัญ
screenOrientation: การตั้งค่าไฟล์ Manifest ของแอปที่ช่วยให้คุณระบุได้ วิธีที่แอปตอบสนองต่อการเปลี่ยนแปลงการวางแนวอุปกรณ์- Jetpack WindowManager: ชุดไลบรารีที่ช่วยให้คุณกำหนดขนาดและสัดส่วนของหน้าต่างแอปได้ โดยสามารถใช้งานร่วมกับ API ระดับ 14 ได้
Activity#setRequestedOrientation(): วิธีที่คุณใช้เปลี่ยน การวางแนวแอปได้ขณะรันไทม์
คอลเล็กชันที่มีคำแนะนำนี้
คู่มือนี้เป็นส่วนหนึ่งของคอลเล็กชันคู่มือฉบับย่อที่คัดสรรมาแล้ว ซึ่งครอบคลุมเป้าหมายการพัฒนา Android ในวงกว้างขึ้น