การรองรับขนาดการแสดงผลที่แตกต่างกันช่วยให้ผู้ใช้เข้าถึงแอปของคุณได้จากอุปกรณ์ที่หลากหลายที่สุด และมีจำนวนผู้ใช้มากที่สุด
หากต้องการรองรับขนาดการแสดงผลให้ได้มากที่สุด ไม่ว่าจะเป็นหน้าจออุปกรณ์ต่างๆ หรือหน้าต่างแอปต่างๆ ในโหมดหลายหน้าต่าง ให้ออกแบบเลย์เอาต์ของแอปให้ตอบสนองและปรับเปลี่ยนตามอุปกรณ์ เลย์เอาต์ที่ตอบสนองตามอุปกรณ์/ปรับตามอุปกรณ์มอบประสบการณ์การใช้งานที่ ได้รับการเพิ่มประสิทธิภาพโดยไม่คำนึงถึงขนาดการแสดงผล ซึ่งช่วยให้แอปของคุณ รองรับโทรศัพท์ แท็บเล็ต อุปกรณ์แบบพับ อุปกรณ์ ChromeOS การวางแนวตั้งและแนวนอน รวมถึงการกำหนดค่าการแสดงผลที่ปรับขนาดได้ เช่น โหมดแยกหน้าจอ และหน้าต่างเดสก์ท็อป
เลย์เอาต์ที่ปรับเปลี่ยนตามพื้นที่โฆษณาจะเปลี่ยนแปลงตามพื้นที่โฆษณาที่มีอยู่ การเปลี่ยนแปลง มีตั้งแต่การปรับเลย์เอาต์เล็กๆ น้อยๆ ที่เติมเต็มพื้นที่ (การออกแบบที่ปรับเปลี่ยนตามพื้นที่โฆษณา) ไปจนถึง การแทนที่เลย์เอาต์หนึ่งด้วยอีกเลย์เอาต์หนึ่งโดยสมบูรณ์ เพื่อให้แอปของคุณรองรับ ขนาดการแสดงผลต่างๆ ได้ดีที่สุด (การออกแบบที่ปรับเปลี่ยนตามอุปกรณ์)
Jetpack Compose เป็นชุดเครื่องมือ UI แบบประกาศสิ่งที่ต้องการ จึงเหมาะสำหรับการออกแบบและ การใช้เลย์เอาต์ที่เปลี่ยนแปลงแบบไดนามิกเพื่อแสดงเนื้อหาแตกต่างกันใน ขนาดการแสดงผลต่างๆ
ระบุการเปลี่ยนแปลงเลย์เอาต์ขนาดใหญ่สำหรับ Composable ระดับเนื้อหาอย่างชัดเจน
Composable ระดับแอปและระดับเนื้อหาจะใช้พื้นที่แสดงผลทั้งหมดที่แอปของคุณใช้ได้ สำหรับ Composable ประเภทนี้ คุณอาจต้องเปลี่ยนเลย์เอาต์โดยรวมของแอปในจอแสดงผลขนาดใหญ่
หลีกเลี่ยงการใช้ค่าฮาร์ดแวร์จริงในการตัดสินใจเรื่องเลย์เอาต์ คุณอาจ อยากตัดสินใจโดยอิงตามมูลค่าที่จับต้องได้ที่แน่นอน (อุปกรณ์เป็นแท็บเล็ต ใช่ไหม หน้าจอจริงมีสัดส่วนภาพที่แน่นอนไหม) แต่คำตอบของคำถามเหล่านี้อาจไม่มีประโยชน์ในการพิจารณาพื้นที่ที่ใช้ได้สำหรับ UI
ในแท็บเล็ต แอปอาจทำงานในโหมดหลายหน้าต่าง ซึ่งหมายความว่าแอป อาจแยกหน้าจอกับแอปอื่น ในโหมดการแสดงหน้าต่างบนเดสก์ท็อปหรือใน ChromeOS แอปอาจอยู่ในหน้าต่างที่ปรับขนาดได้ อาจมีหน้าจอจริงมากกว่า 1 จอ เช่น ในอุปกรณ์แบบพับได้ ในกรณีเหล่านี้ทั้งหมด ขนาดหน้าจอจริงไม่เกี่ยวข้องกับการตัดสินใจว่าจะแสดงเนื้อหาอย่างไร
แต่ให้ตัดสินใจโดยอิงตามสัดส่วนจริงของหน้าจอที่จัดสรรให้กับ แอปของคุณตามที่อธิบายไว้ในเมตริกหน้าต่างปัจจุบันที่จัดทำโดยไลบรารี WindowManager ของ Jetpack ดูตัวอย่างวิธีใช้ WindowManager ในแอป Compose ได้ที่ตัวอย่าง JetNews
การทำให้เลย์เอาต์ปรับเปลี่ยนตามพื้นที่แสดงผลที่มีอยู่ยังช่วยลด ปริมาณการจัดการพิเศษที่จำเป็นต่อการรองรับแพลตฟอร์มอย่าง ChromeOS และรูปแบบ อุปกรณ์อย่างแท็บเล็ตและอุปกรณ์พับได้ด้วย
เมื่อกำหนดเมตริกของพื้นที่ที่พร้อมใช้งานสำหรับแอปแล้ว ให้แปลง ขนาดดิบเป็นคลาสขนาดหน้าต่างตามที่อธิบายไว้ในใช้คลาสขนาดหน้าต่าง คลาสขนาดหน้าต่างคือเบรกพอยต์ที่ออกแบบมาเพื่อสร้างสมดุลระหว่างความเรียบง่ายของตรรกะของแอปกับความยืดหยุ่นในการเพิ่มประสิทธิภาพแอปสำหรับขนาดการแสดงผลส่วนใหญ่
คลาสขนาดหน้าต่างหมายถึงหน้าต่างโดยรวมของแอป ดังนั้นให้ใช้คลาส สำหรับการตัดสินใจเกี่ยวกับเลย์เอาต์ที่จะส่งผลต่อเลย์เอาต์โดยรวมของแอป คุณส่งคลาสขนาดหน้าต่างเป็นสถานะ หรือจะใช้ตรรกะเพิ่มเติมเพื่อสร้างสถานะที่ได้มาเพื่อส่งไปยังฟังก์ชันที่ประกอบกันได้แบบซ้อนกันก็ได้
@Composable fun MyApp( windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().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 แต่ละรายการที่นำกลับมาใช้ซ้ำได้ไม่ควรขึ้นอยู่กับข้อมูลขนาดการแสดงผลส่วนกลางโดยนัย
ลองนึกภาพ Composable แบบซ้อนที่ใช้เลย์เอาต์รายการ-รายละเอียด ซึ่งอาจแสดงบานหน้าต่างเดียวหรือ 2 บานหน้าต่างแบบเคียงข้างกัน
การตัดสินใจเกี่ยวกับรายการและรายละเอียดควรเป็นส่วนหนึ่งของเลย์เอาต์โดยรวมของแอป ดังนั้นการตัดสินใจจึงส่งต่อจาก Composable ระดับเนื้อหา
@Composable fun AdaptivePane( showOnePane: Boolean, /* ... */ ) { if (showOnePane) { OnePane(/* ... */) } else { TwoPane(/* ... */) } }
จะเกิดอะไรขึ้นหากคุณต้องการให้ Composable เปลี่ยนเลย์เอาต์โดยอิสระตาม พื้นที่แสดงผลที่มีอยู่ เช่น การ์ดที่แสดงรายละเอียดเพิ่มเติม หากมีพื้นที่ คุณต้องการใช้ตรรกะบางอย่างตามขนาด Display ที่มีอยู่ แต่จะใช้ขนาดใดโดยเฉพาะ
หลีกเลี่ยงการพยายามใช้ขนาดหน้าจอจริงของอุปกรณ์ ค่านี้จะไม่ถูกต้องสำหรับหน้าจอประเภทต่างๆ และจะไม่ถูกต้องหากแอปไม่ได้แสดงแบบเต็มหน้าจอ
เนื่องจาก 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 โปรดทราบว่าระบบจะส่ง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 เป็นแอปที่ใช้เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์เพื่อ รองรับขนาดการแสดงผลต่างๆ
วิดีโอ