การรองรับหน้าจอขนาดต่างๆ ช่วยให้ผู้ใช้จำนวนมากและอุปกรณ์ที่หลากหลายเข้าถึงแอปของคุณได้
ออกแบบเลย์เอาต์แอปให้ปรับเปลี่ยนตามอุปกรณ์และรองรับหน้าจอหลายขนาดมากที่สุด เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์/ปรับเปลี่ยนได้ช่วยให้ผู้ใช้ได้รับประสบการณ์ที่มีประสิทธิภาพไม่ว่าหน้าจอจะมีขนาดเท่าใดก็ตาม ทำให้แอปสามารถรองรับโทรศัพท์, แท็บเล็ต, อุปกรณ์แบบพับได้, อุปกรณ์ ChromeOS, การวางในแนวตั้งและแนวนอน รวมถึงการกำหนดค่าที่ปรับขนาดได้ เช่น โหมดหลายหน้าต่าง
เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์/ปรับเปลี่ยนได้จะเปลี่ยนแปลงตามพื้นที่แสดงผลที่มีอยู่ การเปลี่ยนแปลงมีตั้งแต่การปรับเลย์เอาต์เล็กน้อยเพื่อใช้พื้นที่ว่างให้เกิดประโยชน์สูงสุด (การออกแบบที่ปรับเปลี่ยนตามพื้นที่โฆษณา) ไปจนถึงการเปลี่ยนเลย์เอาต์หนึ่งด้วยอีกเลย์เอาต์หนึ่งโดยสมบูรณ์เพื่อให้แอปรองรับขนาดการแสดงผลที่แตกต่างกันได้ดีที่สุด (การออกแบบที่ปรับเปลี่ยนได้)
ในฐานะชุดเครื่องมือ UI แบบประกาศสิ่งที่ต้องการ Jetpack Compose เหมาะสําหรับการออกแบบและการใช้เลย์เอาต์ที่เปลี่ยนแปลงแบบไดนามิกเพื่อแสดงผลเนื้อหาในลักษณะที่แตกต่างกันในขนาดการแสดงผลที่หลากหลาย
ทำการเปลี่ยนแปลงเลย์เอาต์ขนาดใหญ่สำหรับคอมโพสิเบิลระดับหน้าจออย่างชัดเจน
เมื่อใช้ Compose เพื่อวางเลย์เอาต์แอปพลิเคชันทั้งหมด คอมโพสิเบิลระดับแอปและระดับหน้าจอจะใช้พื้นที่ทั้งหมดที่แอปได้รับเพื่อแสดงผล เมื่อออกแบบในระดับนี้ คุณอาจต้องเปลี่ยนเลย์เอาต์โดยรวมของหน้าจอเพื่อใช้ประโยชน์จากหน้าจอขนาดใหญ่
หลีกเลี่ยงการใช้ค่าที่ฮาร์ดแวร์และสินค้าที่จับต้องได้ในการตัดสินใจเลือกเลย์เอาต์ คุณอาจอยากตัดสินใจตามมูลค่าที่จับต้องได้แบบคงที่ (อุปกรณ์เป็นแท็บเล็ตไหม หน้าจอจริงมีสัดส่วนการแสดงผลหรือไม่) แต่คำตอบสำหรับคำถามเหล่านี้อาจไม่มีประโยชน์สำหรับการกำหนดพื้นที่ที่ UI ใช้งานได้
ในแท็บเล็ต แอปอาจทำงานในโหมดหลายหน้าต่าง ซึ่งหมายความว่าแอปอาจแยกหน้าจอกับแอปอื่นอยู่ ใน ChromeOS แอปอาจอยู่ในหน้าต่างที่ปรับขนาดได้ อุปกรณ์อาจมีหน้าจอจริงมากกว่า 1 หน้าจอ เช่น อุปกรณ์แบบพับได้ ในทุกกรณีเหล่านี้ ขนาดหน้าจอจริงไม่เกี่ยวข้องกับการตัดสินใจเลือกวิธีแสดงเนื้อหา
แต่คุณควรตัดสินใจตามส่วนจริงของหน้าจอที่จัดสรรให้กับแอป เช่น เมตริกหน้าต่างปัจจุบันที่ได้จากไลบรารี WindowManager ของ Jetpack หากต้องการดูวิธีใช้ WindowManager ในแอป Compose โปรดดูตัวอย่าง JetNews
การใช้แนวทางนี้จะทำให้แอปมีความยืดหยุ่นมากขึ้น เนื่องจากจะทำงานได้ดีในสถานการณ์ทั้งหมดข้างต้น การทำเลย์เอาต์ให้ปรับตามพื้นที่หน้าจอที่พร้อมใช้งานยังช่วยลดจำนวนการจัดการพิเศษเพื่อรองรับแพลตฟอร์มต่างๆ เช่น ChromeOS และรูปแบบอุปกรณ์ต่างๆ เช่น แท็บเล็ตและอุปกรณ์แบบพับได้
เมื่อคุณสังเกตเห็นพื้นที่ที่เกี่ยวข้องซึ่งพร้อมใช้งานสําหรับแอปแล้ว การเปลี่ยนขนาดดิบเป็นคลาสขนาดที่สื่อความหมายจะมีประโยชน์ตามที่อธิบายไว้ในใช้คลาสขนาดหน้าต่าง โดยจะจัดกลุ่มขนาดลงในที่เก็บข้อมูลขนาดมาตรฐาน ซึ่งเป็นเบรกพอยท์ที่ออกแบบมาเพื่อ สร้างสมดุลระหว่างความเรียบง่ายกับความยืดหยุ่นในการเพิ่มประสิทธิภาพแอปสำหรับ กรณีที่ไม่ซ้ำส่วนใหญ่ คลาสขนาดเหล่านี้หมายถึงหน้าต่างโดยรวมของแอป ดังนั้นให้ใช้คลาสเหล่านี้ในการตัดสินใจเกี่ยวกับเลย์เอาต์ที่ส่งผลต่อเลย์เอาต์หน้าจอโดยรวม คุณสามารถส่งคลาสขนาดเหล่านี้เป็นสถานะ หรือจะใช้ตรรกะเพิ่มเติมเพื่อสร้างสถานะที่มาจากแหล่งอื่นเพื่อส่งต่อไปยังคอมโพสิชันที่ฝังอยู่ก็ได้
@Composable fun MyApp( windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass ) { // Perform logic on the size class to decide whether to show the top app bar. val showTopAppBar = windowSizeClass.windowHeightSizeClass != WindowHeightSizeClass.COMPACT // MyScreen knows nothing about window sizes, and performs logic based on a Boolean flag. MyScreen( showTopAppBar = showTopAppBar, /* ... */ ) }
แนวทางแบบเป็นชั้นนี้จะจำกัดตรรกะขนาดหน้าจอไว้ที่ตำแหน่งเดียว แทนที่จะกระจายตรรกะดังกล่าวไปทั่วแอปในหลายๆ ตําแหน่งที่ต้องซิงค์กัน ตำแหน่งเดียวนี้จะสร้างสถานะ ซึ่งสามารถส่งต่อไปยังคอมโพสิเบิลอื่นๆ ได้อย่างชัดเจน เช่นเดียวกับที่คุณทำกับสถานะแอปอื่นๆ การส่งผ่านสถานะอย่างชัดเจนจะลดความซับซ้อนของคอมโพสิเบิลแต่ละรายการ เนื่องจากจะเป็นฟังก์ชันคอมโพสิเบิลปกติที่ใช้คลาสขนาดหรือการกําหนดค่าที่ระบุพร้อมกับข้อมูลอื่นๆ
คอมโพสิเบิลที่ฝังไว้อย่างยืดหยุ่นสามารถนำมาใช้ซ้ำได้
Composable จะใช้งานได้ซ้ำมากขึ้นเมื่อนำไปวางไว้ในที่ที่หลากหลาย หากคอมโพสิเบิลถือว่าจะมีการจัดวางในตำแหน่งที่แน่นอนและมีขนาดที่เฉพาะเจาะจงเสมอ การนำไปใช้ซ้ำในที่อื่นในตำแหน่งอื่นหรือที่มีพื้นที่ว่างแตกต่างกันก็จะทำได้ยากขึ้น ซึ่งหมายความว่าคอมโพสิเบิลแบบใช้ซ้ำได้แต่ละรายการควรหลีกเลี่ยงการพึ่งพาข้อมูลขนาด "ส่วนกลาง" โดยนัย
พิจารณาตัวอย่างต่อไปนี้ ลองจินตนาการถึงคอมโพสิเบิลที่ฝังอยู่ซึ่งใช้เลย์เอาต์รายการแบบละเอียด ซึ่งอาจแสดงแผง 1 แผงหรือ 2 แผงเคียงข้างกัน
เราอยากให้การตัดสินใจนี้เป็นส่วนหนึ่งของเลย์เอาต์โดยรวมสำหรับแอป จึงส่งต่อการตัดสินใจจาก Composable ระดับหน้าจออย่างที่เห็นด้านบน
@Composable fun AdaptivePane( showOnePane: Boolean, /* ... */ ) { if (showOnePane) { OnePane(/* ... */) } else { TwoPane(/* ... */) } }
จะเกิดอะไรขึ้นหากเราต้องการให้ Composable เปลี่ยนเลย์เอาต์อย่างอิสระตามพื้นที่ว่างที่มีอยู่ เช่น การ์ดที่ต้องการแสดงรายละเอียดเพิ่มเติมหากมีพื้นที่เพียงพอ เราต้องการใช้ตรรกะตามขนาดที่มี แต่จะเน้นขนาดใดโดยเฉพาะ
อย่างที่เห็นด้านบน เราควรหลีกเลี่ยงการพยายามใช้ขนาดของหน้าจอจริงของอุปกรณ์ ข้อมูลนี้จะไม่ถูกต้องสำหรับหน้าจอหลายหน้าจอ และจะไม่ถูกต้องหากแอปไม่ได้แสดงแบบเต็มหน้าจอ
เนื่องจากคอมโพสิเบิลไม่ใช่คอมโพสิเบิลระดับหน้าจอ เราจึงไม่ควรใช้เมตริกกรอบเวลาปัจจุบันโดยตรงเพื่อเพิ่มความสามารถในการนํากลับมาใช้ซ้ำให้ได้สูงสุด หากวางคอมโพเนนต์โดยมีการเว้นวรรค (เช่น สำหรับการฝัง) หรือหากมีคอมโพเนนต์ เช่น แถบนําทางหรือแถบแอป พื้นที่ที่ใช้ได้ของคอมโพสิเบิลอาจแตกต่างจากพื้นที่โดยรวมที่ใช้ได้ของแอปอย่างมาก
ดังนั้น เราควรใช้ความกว้างที่คอมโพสิเบิลได้รับจริงเพื่อแสดงผล เรามี 2 วิธีในการรับค่าความกว้างนั้น
หากต้องการเปลี่ยนตำแหน่งหรือวิธีการแสดงเนื้อหา คุณสามารถใช้ชุดตัวแก้ไขหรือเลย์เอาต์ที่กำหนดเองเพื่อทำให้เลย์เอาต์ปรับเปลี่ยนตามอุปกรณ์ได้ ซึ่งอาจเป็นเรื่องง่ายๆ อย่างการกำหนดให้เด็กเติมเต็มพื้นที่ที่มีอยู่ทั้งหมด หรือจัดองค์ประกอบย่อยด้วยคอลัมน์หลายคอลัมน์หากมีพื้นที่เพียงพอ
หากต้องการเปลี่ยนสิ่งที่แสดง คุณสามารถใช้ BoxWithConstraints
แทนได้ Composable นี้มีข้อจำกัดการวัดที่คุณสามารถใช้เพื่อเรียกใช้ Composable ต่างๆ โดยอิงตามพื้นที่ว่างที่มีอยู่ อย่างไรก็ตาม การดำเนินการนี้จะมีค่าใช้จ่ายบางส่วน เนื่องจาก BoxWithConstraints
จะเลื่อนองค์ประกอบไปจนถึงระยะของเลย์เอาต์เมื่อทราบข้อจำกัดเหล่านี้ ทำให้มีการดำเนินการเพิ่มเติมระหว่างเลย์เอาต์
@Composable fun Card(/* ... */) { BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(/* ... */) Title(/* ... */) } } else { Row { Column { Title(/* ... */) Description(/* ... */) } Image(/* ... */) } } } }
ตรวจสอบว่าข้อมูลทั้งหมดพร้อมใช้งานสำหรับขนาดต่างๆ
เมื่อใช้ประโยชน์จากพื้นที่หน้าจอเพิ่มเติม คุณอาจมีพื้นที่ในการแสดงเนื้อหาต่อผู้ใช้มากกว่าในหน้าจอขนาดเล็ก เมื่อใช้คอมโพสิเบิลที่มีลักษณะการทํางานนี้ คุณอาจต้องการทําให้มีประสิทธิภาพและโหลดข้อมูลเป็นผลข้างเคียงของขนาดปัจจุบัน
อย่างไรก็ตาม การทำเช่นนี้ขัดกับหลักการของโฟลว์ข้อมูลแบบทิศทางเดียว ซึ่งก็คือข้อมูลสามารถสร้างขึ้นและจัดเตรียมให้กับ 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
Boolean flag ขึ้นเพื่อให้ระบบรักษาสถานะของผู้ใช้ไว้เมื่อการปรับขนาดทําให้เลย์เอาต์สลับระหว่างการซ่อนและแสดงคําอธิบาย ดังนี้
@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 ให้ใช้ประโยชน์จากพื้นที่ที่มีอยู่
- ตอบกลับ เป็นตัวอย่างแบบปรับเปลี่ยนได้เพื่อให้รองรับอุปกรณ์เคลื่อนที่ แท็บเล็ต และอุปกรณ์แบบพับได้
- ตอนนี้มีใน Android เป็นแอปที่ใช้เลย์เอาต์ที่ปรับเปลี่ยนได้เพื่อรองรับหน้าจอขนาดต่างๆ
วิดีโอ
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- การแมปคอมโพเนนต์กับโค้ดที่มีอยู่
- ข้อมูลเบื้องต้นเกี่ยวกับการจัดวาง
- ระยะของ Jetpack Compose