การรองรับขนาดการแสดงผลที่แตกต่างกันช่วยให้แอปของคุณเข้าถึงอุปกรณ์ได้หลากหลายที่สุดและผู้ใช้จำนวนมากที่สุด
หากต้องการรองรับขนาดการแสดงผลให้ได้มากที่สุด ไม่ว่าจะเป็นหน้าจออุปกรณ์ที่แตกต่างกันหรือหน้าต่างแอปที่แตกต่างกันในโหมดหลายหน้าต่าง ให้ออกแบบเลย์เอาต์แอปให้ปรับเปลี่ยนตามอุปกรณ์และปรับเปลี่ยนได้ เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์/ปรับเปลี่ยนได้จะมอบประสบการณ์ของผู้ใช้ที่เพิ่มประสิทธิภาพไม่ว่าหน้าจอจะมีขนาดเท่าใดก็ตาม ซึ่งช่วยให้แอปของคุณรองรับโทรศัพท์ แท็บเล็ต อุปกรณ์แบบพับได้ อุปกรณ์ ChromeOS การวางแนวตั้งและแนวนอน รวมถึงการกำหนดค่าการแสดงผลที่ปรับขนาดได้ เช่น โหมดแยกหน้าจอและหน้าต่างเดสก์ท็อป
เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์/ปรับเปลี่ยนได้จะเปลี่ยนแปลงตามพื้นที่แสดงผลที่พร้อมใช้งาน การเปลี่ยนแปลงมีตั้งแต่การปรับเลย์เอาต์เล็กน้อยเพื่อเติมเต็มพื้นที่ (การออกแบบที่ปรับเปลี่ยนตามอุปกรณ์) ไปจนถึงการแทนที่เลย์เอาต์หนึ่งด้วยอีกเลย์เอาต์หนึ่งโดยสมบูรณ์ เพื่อให้แอปของคุณรองรับขนาดการแสดงผลที่แตกต่างกันได้ดีที่สุด (การออกแบบที่ปรับเปลี่ยนตามอุปกรณ์)
ในฐานะชุดเครื่องมือ UI แบบประกาศ Jetpack Compose เหมาะอย่างยิ่งสำหรับการออกแบบและใช้เลย์เอาต์ที่เปลี่ยนแปลงแบบไดนามิกเพื่อแสดงผลเนื้อหาที่แตกต่างกันในขนาดการแสดงผลที่แตกต่างกัน
ทักษะ Android
ดูใน GitHubทำให้แอปปรับเปลี่ยนตามอุปกรณ์ได้
adaptive เพื่ออัปเดต UI ของแอปให้ปรับเปลี่ยนตามอุปกรณ์ Android และจอแสดงผลต่างๆandroid skills add adaptiveทำให้การเปลี่ยนแปลงเลย์เอาต์ขนาดใหญ่สำหรับ Composable ระดับเนื้อหามีความชัดเจน
Composable ระดับแอปและระดับเนื้อหาจะใช้พื้นที่แสดงผลทั้งหมดที่แอปของคุณมี สำหรับ Composable ประเภทเหล่านี้ การเปลี่ยนเลย์เอาต์โดยรวมของแอปบนจอแสดงผลขนาดใหญ่อาจเป็นเรื่องที่สมเหตุสมผล
หลีกเลี่ยงการใช้ค่าฮาร์ดแวร์จริงในการตัดสินใจเกี่ยวกับเลย์เอาต์ คุณอาจอยากตัดสินใจโดยอิงตามมูลค่าที่จับต้องได้ (อุปกรณ์เป็นแท็บเล็ตใช่ไหม หน้าจอจริงมีสัดส่วนภาพที่แน่นอนหรือไม่) แต่คำตอบของคำถามเหล่านี้อาจไม่มีประโยชน์ในการกำหนดพื้นที่ว่างสำหรับ UI ของคุณ
ในแท็บเล็ต แอปอาจทำงานในโหมดหลายหน้าต่าง ซึ่งหมายความว่าแอปอาจแยกหน้าจอกับแอปอื่น ในโหมดหน้าต่างเดสก์ท็อปหรือใน ChromeOS แอปอาจอยู่ในหน้าต่างที่ปรับขนาดได้ หรืออาจมีหน้าจอจริงมากกว่า 1 หน้าจอ เช่น ในอุปกรณ์แบบพับได้ ในกรณีเหล่านี้ทั้งหมด ขนาดหน้าจอจริงจะไม่เกี่ยวข้องกับการตัดสินใจว่าจะแสดงเนื้อหาอย่างไร
แต่ให้ตัดสินใจโดยอิงตามส่วนจริงของหน้าจอที่จัดสรรให้กับแอปของคุณตามที่อธิบายไว้ในเมตริกหน้าต่างปัจจุบันที่ได้จากไลบรารี WindowManager ของ Jetpack ดูตัวอย่างวิธีใช้ WindowManager ในแอป Compose ได้ที่ตัวอย่าง JetNews
การทำให้เลย์เอาต์ปรับเปลี่ยนตามพื้นที่แสดงผลที่พร้อมใช้งานยังช่วยลดปริมาณการจัดการพิเศษที่จำเป็นต่อการรองรับแพลตฟอร์มต่างๆ เช่น ChromeOS และรูปแบบต่างๆ เช่น แท็บเล็ตและอุปกรณ์แบบพับได้
เมื่อกำหนดเมตริกของพื้นที่ที่พร้อมใช้งานสำหรับแอปแล้ว ให้แปลงขนาดดิบเป็นคลาสขนาดหน้าต่างตามที่อธิบายไว้ในใช้คลาสขนาดหน้าต่าง คลาสขนาดหน้าต่างคือเบรกพอยต์ที่ออกแบบมาเพื่อสร้างสมดุลระหว่างความเรียบง่ายของตรรกะแอปกับความยืดหยุ่นในการเพิ่มประสิทธิภาพแอปสำหรับจอแสดงผลขนาดต่างๆ ส่วนใหญ่
คลาสขนาดหน้าต่างหมายถึงหน้าต่างโดยรวมของแอป ดังนั้นให้ใช้คลาสเหล่านี้ในการตัดสินใจเกี่ยวกับเลย์เอาต์ที่ส่งผลต่อเลย์เอาต์โดยรวมของแอป คุณสามารถส่งคลาสขนาดหน้าต่างลงมาเป็นสถานะ หรือจะใช้ตรรกะเพิ่มเติมเพื่อสร้างสถานะที่ได้มาเพื่อส่งไปยัง Composable ที่ฝังอยู่ก็ได้
@Composable fun MyApp( windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo(supportLargeAndXLargeWidth = true).windowSizeClass ) { // Decide whether to show the top app bar based on window size class. val showTopAppBar = windowSizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND) // MyScreen logic is based on the showTopAppBar boolean flag. MyScreen( showTopAppBar = showTopAppBar, /* ... */ ) }
แนวทางแบบเลเยอร์จะจำกัดตรรกะขนาดการแสดงผลไว้ที่ตำแหน่งเดียว แทนที่จะกระจายไปทั่วแอปในหลายๆ ตำแหน่งที่ต้องซิงค์กัน ตำแหน่งเดียวจะสร้างสถานะ ซึ่งสามารถส่งต่อไปยัง Composable อื่นๆ ได้อย่างชัดเจนเช่นเดียวกับสถานะแอปอื่นๆ การส่งสถานะอย่างชัดเจนจะช่วยลดความซับซ้อนของ Composable แต่ละรายการ เนื่องจาก Composable จะใช้คลาสขนาดหน้าต่างหรือการกำหนดค่าที่ระบุพร้อมกับข้อมูลอื่นๆ
Composable ที่ฝังแบบยืดหยุ่นสามารถนำมาใช้ซ้ำได้
คอมโพสิเบิลจะนำกลับมาใช้ใหม่ได้มากขึ้นเมื่อสามารถวางในตำแหน่งต่างๆ ได้หลากหลาย หากต้องวาง Composable ในตำแหน่งที่เฉพาะเจาะจงและมีขนาดที่เฉพาะเจาะจง Composable นั้นก็ไม่น่าจะนำมาใช้ซ้ำในบริบทอื่นๆ ได้ ซึ่งหมายความว่า Composable แต่ละรายการที่นำมาใช้ซ้ำได้ควรหลีกเลี่ยงการขึ้นอยู่กับข้อมูลขนาดการแสดงผลส่วนกลางโดยนัย
ลองนึกภาพ Composable ที่ฝังอยู่ซึ่งใช้เลย์เอาต์แบบรายละเอียดรายการ ซึ่งอาจแสดงแผงเดียวหรือ 2 แผงข้างกัน
การตัดสินใจเกี่ยวกับรายละเอียดรายการควรเป็นส่วนหนึ่งของเลย์เอาต์โดยรวมของแอป ดังนั้นการตัดสินใจจึงส่งต่อจาก Composable ระดับเนื้อหา
@Composable fun AdaptivePane( showOnePane: Boolean, /* ... */ ) { if (showOnePane) { OnePane(/* ... */) } else { TwoPane(/* ... */) } }
จะเกิดอะไรขึ้นหากคุณต้องการให้ Composable เปลี่ยนเลย์เอาต์อย่างอิสระตามพื้นที่แสดงผลที่พร้อมใช้งาน เช่น การ์ดที่แสดงรายละเอียดเพิ่มเติมหากมีพื้นที่เพียงพอ คุณต้องการใช้ตรรกะบางอย่างตามขนาดการแสดงผลที่ใช้ได้ แต่ขนาดใดโดยเฉพาะ
หลีกเลี่ยงการพยายามใช้ขนาดหน้าจอจริงของอุปกรณ์ ซึ่งจะไม่ถูกต้องสำหรับหน้าจอประเภทต่างๆ และจะไม่ถูกต้องหากแอปไม่ได้แสดงแบบเต็มหน้าจอ
เนื่องจาก Composable ไม่ใช่ Composable ระดับเนื้อหา จึงไม่ควรใช้เมตริกหน้าต่างปัจจุบันโดยตรง
หากคอมโพเนนต์วางอยู่โดยมีระยะห่างจากขอบ (เช่น มีส่วนที่เว้นไว้) หรือหากแอปมีคอมโพเนนต์ เช่น แถบนำทางหรือแถบด้านบนของแอป พื้นที่แสดงผลที่ Composable ใช้ได้อาจแตกต่างจากพื้นที่ทั้งหมดที่แอปใช้ได้อย่างมาก
ใช้ความกว้างที่ Composable ได้รับจริงเพื่อแสดงผลตัวเอง คุณมี 2 ตัวเลือกในการกำหนดความกว้างดังกล่าว ดังนี้
หากต้องการเปลี่ยนตำแหน่งหรือวิธีแสดงเนื้อหา ให้ใช้คอลเล็กชันของตัวแก้ไขหรือเลย์เอาต์ที่กำหนดเองเพื่อทำให้เลย์เอาต์ปรับเปลี่ยนตามอุปกรณ์ ซึ่งอาจทำได้ง่ายๆ เช่น ให้องค์ประกอบย่อยเติมพื้นที่ว่างทั้งหมด หรือจัดวางองค์ประกอบย่อยที่มีหลายคอลัมน์หากมีพื้นที่เพียงพอ
หากต้องการเปลี่ยนสิ่งที่แสดง ให้ใช้
BoxWithConstraintsเป็นทางเลือกที่มีประสิทธิภาพมากกว่าBoxWithConstraintsมีข้อจำกัดด้านการวัดที่คุณใช้เรียก Composable ต่างๆ ได้โดยอิงตามพื้นที่แสดงผลที่พร้อมใช้งาน อย่างไรก็ตาม วิธีนี้มีข้อเสียอยู่บ้าง เนื่องจากBoxWithConstraintsจะเลื่อนการจัดองค์ประกอบออกไปจนถึงระยะเลย์เอาต์เมื่อทราบข้อจำกัดเหล่านี้แล้ว ซึ่งทำให้ต้องทำงานมากขึ้นในระหว่างการจัดเลย์เอาต์
@Composable fun Card(/* ... */) { BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(/* ... */) Title(/* ... */) } } else { Row { Column { Title(/* ... */) Description(/* ... */) } Image(/* ... */) } } } }
ทำให้ข้อมูลทั้งหมดพร้อมใช้งานสำหรับการแสดงผลขนาดต่างๆ
เมื่อใช้ Composable ที่ใช้ประโยชน์จากพื้นที่แสดงผลเพิ่มเติม คุณอาจต้องการเพิ่มประสิทธิภาพและโหลดข้อมูลเป็นผลข้างเคียงของขนาดการแสดงผลปัจจุบัน
อย่างไรก็ตาม การทำเช่นนี้ขัดต่อหลักการของการไหลของข้อมูลแบบทิศทางเดียว ซึ่งข้อมูลสามารถยกขึ้นและส่งไปยัง Composable เพื่อแสดงผลได้อย่างเหมาะสม ควรระบุข้อมูลที่เพียงพอให้กับ Composable เพื่อให้ Composable มีเนื้อหาที่เพียงพอสำหรับขนาดการแสดงผลเสมอ แม้ว่าเนื้อหาบางส่วนอาจไม่ได้ใช้เสมอไปก็ตาม
@Composable fun Card( imageUrl: String, title: String, description: String ) { BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(imageUrl) Title(title) } } else { Row { Column { Title(title) Description(description) } Image(imageUrl) } } } }
จากตัวอย่าง Card โปรดทราบว่าระบบจะส่ง description ไปยัง Card เสมอ แม้ว่าจะใช้ description เฉพาะเมื่อความกว้างอนุญาตให้แสดงเท่านั้น แต่ Card ต้องใช้ description เสมอ ไม่ว่าความกว้างที่ใช้ได้จะเป็นเท่าใดก็ตาม
การส่งเนื้อหาที่เพียงพอเสมอจะทำให้เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์ง่ายขึ้นโดยทำให้มีสถานะน้อยลง และหลีกเลี่ยงการทริกเกอร์ผลข้างเคียงเมื่อสลับระหว่างขนาดการแสดงผล (ซึ่งอาจเกิดขึ้นเนื่องจากการปรับขนาดหน้าต่าง การเปลี่ยนการวางแนว หรือการพับและกางอุปกรณ์)
หลักการนี้ยังช่วยให้คงสถานะไว้ได้แม้จะมีการเปลี่ยนแปลงเลย์เอาต์ การยกข้อมูลที่อาจไม่ได้ใช้ในขนาดการแสดงผลทั้งหมดจะช่วยให้คุณรักษาสถานะแอปไว้ได้เมื่อขนาดเลย์เอาต์เปลี่ยนแปลง
ตัวอย่างเช่น คุณสามารถยกแฟล็กบูลีน showMore เพื่อให้ระบบคงสถานะแอปไว้เมื่อการปรับขนาดการแสดงผลทำให้เลย์เอาต์สลับไปมาระหว่างการซ่อนและการแสดงเนื้อหา
@Composable fun Card( imageUrl: String, title: String, description: String ) { var showMore by remember { mutableStateOf(false) } BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(imageUrl) Title(title) } } else { Row { Column { Title(title) Description( description = description, showMore = showMore, onShowMoreToggled = { newValue -> showMore = newValue } ) } Image(imageUrl) } } } }
ดูข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับเลย์เอาต์แบบปรับอัตโนมัติใน Compose ได้ที่แหล่งข้อมูลต่อไปนี้
แอปตัวอย่าง
- CanonicalLayouts เป็นที่เก็บข้อมูลของรูปแบบการออกแบบที่ได้รับการพิสูจน์แล้วว่ามอบประสบการณ์ของผู้ใช้ที่ดีที่สุดบนจอแสดงผลขนาดใหญ่
- JetNews แสดงวิธีออกแบบแอปที่ปรับ UI ให้ใช้ประโยชน์จากพื้นที่แสดงผลที่มีอยู่
- Reply เป็นตัวอย่างที่ปรับเปลี่ยนได้สำหรับการรองรับอุปกรณ์เคลื่อนที่ แท็บเล็ต และอุปกรณ์แบบพับได้
- Now in Android เป็นแอปที่ใช้เลย์เอาต์แบบปรับเปลี่ยนได้เพื่อรองรับขนาดการแสดงผลต่างๆ
วิดีโอ