จำกัดการวางแนวของแอปในโทรศัพท์ แต่ไม่ได้จำกัดในอุปกรณ์ที่มีหน้าจอขนาดใหญ่

แอปของคุณทำงานได้ดีในโทรศัพท์ที่อยู่ในแนวนอน คุณจึงจำกัด แอปให้แสดงในแนวนอนเท่านั้น แต่คุณเห็นโอกาสที่จะทำสิ่งต่างๆ ได้มากขึ้นบนหน้าจอขนาดใหญ่ใน แนวนอน

คุณจะทำอย่างไรหากต้องการจำกัดแอปให้แสดงในแนวนอนบนหน้าจอขนาดเล็ก แต่เปิดใช้แนวนอนบนหน้าจอขนาดใหญ่

คำแนะนำนี้เป็นมาตรการชั่วคราวจนกว่าคุณจะปรับปรุงแอปให้รองรับการกำหนดค่าอุปกรณ์ทั้งหมดได้อย่างเต็มรูปแบบ

ผลลัพธ์

แอปจะยังคงอยู่ในแนวตั้งบนหน้าจอขนาดเล็กไม่ว่าจะหมุนอุปกรณ์อย่างไรก็ตาม ในหน้าจอขนาดใหญ่ แอปจะรองรับการวางแนวแนวนอนและแนวตั้ง

ความเข้ากันได้ของเวอร์ชัน

การติดตั้งใช้งานนี้ใช้ได้กับ 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 ในวงกว้างขึ้น

เปิดใช้แอปให้รองรับประสบการณ์ของผู้ใช้ที่ได้รับการเพิ่มประสิทธิภาพในแท็บเล็ต อุปกรณ์พับได้ และอุปกรณ์ ChromeOS

มีคำถามหรือความคิดเห็น

ไปที่หน้าคำถามที่พบบ่อยเพื่อดูคำแนะนำแบบรวดเร็ว หรือติดต่อเราเพื่อบอกความคิดเห็นของคุณ