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

ลองใช้วิธีเขียน
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 ตัวอย่างต่อไปนี้ แสดงวิธีคำนวณคลาสขนาดหน้าต่างและรับการอัปเดตเมื่อใดก็ตามที่ การเปลี่ยนแปลงคลาสขนาดหน้าต่าง:

KotlinJava
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.
   
}
}
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 จากนั้นเลือกเลย์เอาต์ที่เหมาะสมสำหรับคลาสขนาดความกว้างปานกลาง และพิจารณาเพิ่มเลย์เอาต์เฉพาะ

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

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

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