ใช้คลาสขนาดหน้าต่าง

ลองใช้วิธีเขียน
Jetpack Compose เป็นชุดเครื่องมือ UI ที่แนะนําสําหรับ Android ดูวิธีใช้คลาสขนาดหน้าต่างใน Compose

คลาสขนาดหน้าต่างคือชุดจุดหยุดพักของวิวพอร์ตที่แสดงความคิดเห็นซึ่งช่วยคุณออกแบบ พัฒนา และทดสอบเลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์/ที่ปรับเปลี่ยน จุดตัดสมดุลความเรียบง่ายของเลย์เอาต์กับความยืดหยุ่นของการเพิ่มประสิทธิภาพแอปสำหรับกรณีเฉพาะ

คลาสขนาดหน้าต่างจะจัดหมวดหมู่พื้นที่แสดงผลที่พร้อมใช้งานสำหรับแอปเป็นกะทัดรัด กลาง หรือขยาย ระบบจะจัดหมวดหมู่ความกว้างและความสูงที่ใช้ได้แยกกัน ดังนั้นแอปของคุณจะมี Window Size Class 2 รายการเสมอ รายการหนึ่งสำหรับความกว้างและอีกรายการสำหรับความสูง โดยปกติแล้ว ความกว้างที่ใช้ได้จะสำคัญกว่าความสูงที่ใช้ได้ เนื่องจากการเลื่อนในแนวตั้งมีอยู่ทั่วไป ดังนั้นคลาสขนาดหน้าต่างของแถบแนวนอนจึงมีแนวโน้มที่จะเกี่ยวข้องกับ UI ของแอปมากกว่า

รูปที่ 1 การนําเสนอคลาสขนาดหน้าต่างตามความกว้าง
รูปที่ 2 การนําเสนอคลาสขนาดหน้าต่างตามความสูง

ดังที่แสดงในภาพ จุดพักช่วยให้คุณพิจารณาเลย์เอาต์ในแง่ของอุปกรณ์และการกําหนดค่าต่อไปได้ จุดแบ่งกลุ่มขนาดแต่ละจุดแสดงถึงกรณีส่วนใหญ่สำหรับสถานการณ์อุปกรณ์ทั่วไป ซึ่งอาจเป็นกรอบอ้างอิงอันเป็นประโยชน์เมื่อคุณคิดถึงการออกแบบเลย์เอาต์ตามจุดแบ่ง

คลาสขนาด เบรกพอยต์ การนําเสนออุปกรณ์
ความกว้างแบบกะทัดรัด กว้าง < 600dp โทรศัพท์ 99.96% ในแนวตั้ง
ความกว้างปานกลาง 600dp ≤ ความกว้าง < 840dp แท็บเล็ตในโหมดแนวตั้ง 93.73%

หน้าจอด้านในแบบกางออกขนาดใหญ่ที่สุดในแนวตั้ง

ความกว้างที่ขยายออก ความกว้าง ≥ 840dp แท็บเล็ต 97.22% ในแนวนอน

จอแสดงผลด้านในแบบกางออกขนาดใหญ่ที่สุดในแนวนอน

ความสูงแบบกะทัดรัด ความสูง < 480dp โทรศัพท์ 99.78% ในแนวนอน
ความสูงปานกลาง 480dp ≤ ความสูง < 900dp แท็บเล็ต 96.56% ในแนวนอน

โทรศัพท์ 97.59% ในแนวตั้ง

ความสูงที่ขยายออก ความสูง ≥ 900dp แท็บเล็ตในโหมดแนวตั้ง 94.25%

แม้ว่าการแสดงภาพขนาดคลาสเป็นอุปกรณ์จริงจะมีประโยชน์ แต่ขนาดคลาสของหน้าต่างไม่ได้กำหนดโดยขนาดหน้าจอของอุปกรณ์อย่างชัดเจน คลาสขนาดหน้าต่างไม่ได้มีไว้สําหรับตรรกะประเภท isTablet แต่คลาสขนาดหน้าต่างจะกำหนดโดยขนาดหน้าต่างที่ใช้ได้กับแอปพลิเคชันของคุณ โดยไม่คำนึงถึงประเภทอุปกรณ์ที่แอปทำงานอยู่ ซึ่งส่งผลสำคัญ 2 อย่างดังนี้

  • อุปกรณ์ที่จับต้องได้ไม่ได้รับประกันคลาสขนาดหน้าต่างที่เฉพาะเจาะจง พื้นที่หน้าจอที่พร้อมให้แอปของคุณใช้อาจแตกต่างจากขนาดหน้าจอของอุปกรณ์ด้วยเหตุผลหลายประการ ในอุปกรณ์เคลื่อนที่ โหมดแยกหน้าจอจะแบ่งหน้าจอระหว่างแอปพลิเคชัน 2 แอป ใน ChromeOS แอป Android จะแสดงในหน้าต่างแบบเดสก์ท็อปที่ปรับขนาดได้ตามต้องการ อุปกรณ์แบบพับได้อาจมีหน้าจอ 2 หน้าจอที่มีขนาดแตกต่างกัน ซึ่งเข้าถึงได้ทีละหน้าจอโดยพับหรือกางอุปกรณ์

  • คลาสขนาดหน้าต่างอาจเปลี่ยนแปลงตลอดอายุของแอป ขณะที่แอปทำงานอยู่ การเปลี่ยนแปลงการวางแนวของอุปกรณ์ การทำงานแบบมัลติทาสก์ และการพับ/กางอาจทำให้พื้นที่หน้าจอที่ใช้ได้เปลี่ยนแปลง ด้วยเหตุนี้ คลาสขนาดหน้าต่างจึงเป็นแบบไดนามิก และ UI ของแอปควรปรับตาม

Window Size Classes จะเชื่อมโยงกับเบรกพอยต์แบบกะทัดรัด ปานกลาง และขยายในหลักเกณฑ์เลย์เอาต์ Material Design ใช้คลาสขนาดหน้าต่างเพื่อตัดสินใจเกี่ยวกับเลย์เอาต์แอปพลิเคชันระดับสูง เช่น ตัดสินใจว่าจะใช้เลย์เอาต์แคนนอนิกที่เฉพาะเจาะจงเพื่อใช้ประโยชน์จากพื้นที่หน้าจอเพิ่มเติมหรือไม่

คุณสามารถคำนวณ WindowSizeClass โดยใช้ WindowSizeClass#compute() ของ Jetpack ไลบรารี WindowManager ตัวอย่างต่อไปนี้ แสดงวิธีคำนวณคลาสขนาดหน้าต่างและรับการอัปเดตเมื่อใดก็ตามที่ การเปลี่ยนแปลงคลาสขนาดหน้าต่าง:

Kotlin

class MainActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ...

        // 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)
                computeWindowSizeClasses()
            }
        })

        computeWindowSizeClasses()
    }

    private fun computeWindowSizeClasses() {
        val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this)
        val width = metrics.bounds.width()
        val height = metrics.bounds.height()
        val density = resources.displayMetrics.density
        val windowSizeClass = WindowSizeClass.compute(width/density, height/density)
        // COMPACT, MEDIUM, or EXPANDED
        val widthWindowSizeClass = windowSizeClass.windowWidthSizeClass
        // COMPACT, MEDIUM, or EXPANDED
        val heightWindowSizeClass = windowSizeClass.windowHeightSizeClass

        // Use widthWindowSizeClass and heightWindowSizeClass.
    }
}

Java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ...

        // 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);
                computeWindowSizeClasses();
            }
        });

        computeWindowSizeClasses();
    }

    private void computeWindowSizeClasses() {
        WindowMetrics metrics = WindowMetricsCalculator.getOrCreate()
                .computeCurrentWindowMetrics(this);

        int width = metrics.getBounds().width
        int height = metrics.getBounds().height()
        float density = getResources().getDisplayMetrics().density;
        WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density)
        // COMPACT, MEDIUM, or EXPANDED
        WindowWidthSizeClass widthWindowSizeClass = windowSizeClass.getWindowWidthSizeClass()
        // COMPACT, MEDIUM, or EXPANDED
        WindowHeightSizeClass heightWindowSizeClass = windowSizeClass.getWindowHeightSizeClass()

        // Use widthWindowSizeClass and heightWindowSizeClass.
    }
}

ทดสอบคลาสขนาดหน้าต่าง

เมื่อทําการเปลี่ยนแปลงเลย์เอาต์ ให้ทดสอบลักษณะการทํางานของเลย์เอาต์ในหน้าต่างทุกขนาด โดยเฉพาะที่ความกว้างของจุดหยุดแสดงผลแบบกะทัดรัด ปานกลาง และแบบขยาย

หากคุณมีเลย์เอาต์สำหรับหน้าจอขนาดกะทัดรัดอยู่แล้ว ให้เพิ่มประสิทธิภาพเลย์เอาต์สำหรับคลาสขนาดความกว้างแบบขยายก่อน เนื่องจากคลาสขนาดนี้มีพื้นที่มากที่สุดสำหรับเนื้อหาเพิ่มเติมและการเปลี่ยนแปลง UI จากนั้นเลือกเลย์เอาต์ที่เหมาะสมสำหรับคลาสขนาดความกว้างปานกลาง และพิจารณาเพิ่มเลย์เอาต์เฉพาะ

ขั้นตอนถัดไป

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้คลาสขนาดหน้าต่างเพื่อสร้างเลย์เอาต์ที่ปรับเปลี่ยน/ปรับขนาดได้ได้ที่หัวข้อต่อไปนี้

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