คลาสขนาดหน้าต่างคือชุดจุดหยุดพักของวิวพอร์ตที่แสดงความคิดเห็นซึ่งช่วยคุณออกแบบ พัฒนา และทดสอบเลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์/ที่ปรับเปลี่ยน จุดตัดสมดุลความเรียบง่ายของเลย์เอาต์กับความยืดหยุ่นของการเพิ่มประสิทธิภาพแอปสำหรับกรณีเฉพาะ
คลาสขนาดหน้าต่างจะจัดหมวดหมู่พื้นที่แสดงผลที่พร้อมใช้งานสำหรับแอปเป็นกะทัดรัด กลาง หรือขยาย ระบบจะจัดหมวดหมู่ความกว้างและความสูงที่ใช้ได้แยกกัน ดังนั้นแอปของคุณจะมี Window Size Class 2 รายการเสมอ รายการหนึ่งสำหรับความกว้างและอีกรายการสำหรับความสูง โดยปกติแล้ว ความกว้างที่ใช้ได้จะสำคัญกว่าความสูงที่ใช้ได้ เนื่องจากการเลื่อนในแนวตั้งมีอยู่ทั่วไป ดังนั้นคลาสขนาดหน้าต่างของแถบแนวนอนจึงมีแนวโน้มที่จะเกี่ยวข้องกับ UI ของแอปมากกว่า
![](https://developer.android.google.cn/static/develop/ui/compose/images/layouts/adaptive/window-size-classes/window_size_classes_width.png?authuser=4&hl=th)
![](https://developer.android.google.cn/static/develop/ui/compose/images/layouts/adaptive/window-size-classes/window_size_classes_height.png?authuser=4&hl=th)
ดังที่แสดงในภาพ จุดพักช่วยให้คุณพิจารณาเลย์เอาต์ในแง่ของอุปกรณ์และการกําหนดค่าต่อไปได้ จุดแบ่งกลุ่มขนาดแต่ละจุดแสดงถึงกรณีส่วนใหญ่สำหรับสถานการณ์อุปกรณ์ทั่วไป ซึ่งอาจเป็นกรอบอ้างอิงอันเป็นประโยชน์เมื่อคุณคิดถึงการออกแบบเลย์เอาต์ตามจุดแบ่ง
คลาสขนาด | เบรกพอยต์ | การนําเสนออุปกรณ์ |
---|---|---|
ความกว้างแบบกะทัดรัด | กว้าง < 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 จากนั้นเลือกเลย์เอาต์ที่เหมาะสมสำหรับคลาสขนาดความกว้างปานกลาง และพิจารณาเพิ่มเลย์เอาต์เฉพาะ
ขั้นตอนถัดไป
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้คลาสขนาดหน้าต่างเพื่อสร้างเลย์เอาต์ที่ปรับเปลี่ยน/ปรับขนาดได้ได้ที่หัวข้อต่อไปนี้
สำหรับเลย์เอาต์ที่อิงตามการเขียน: รองรับขนาดการแสดงผลที่แตกต่างกัน
สำหรับเลย์เอาต์ตามมุมมอง: การออกแบบที่ปรับเปลี่ยน/ปรับให้เหมาะกับอุปกรณ์ที่มีมุมมอง
ดูข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่ทำให้แอปยอดเยี่ยมในทุกอุปกรณ์และหน้าจอทุกขนาดได้ที่