การรองรับขนาดการแสดงผลต่างๆ ช่วยให้อุปกรณ์หลากหลายประเภทและผู้ใช้จำนวนมากที่สุดเข้าถึงแอปของคุณได้
หากต้องการรองรับขนาดการแสดงผลให้ได้มากที่สุด ไม่ว่าจะเป็นหน้าจออุปกรณ์ต่างๆ หรือหน้าต่างแอปต่างๆ ในโหมดหลายหน้าต่าง ให้ออกแบบเลย์เอาต์ของแอป ให้ปรับเปลี่ยนตามอุปกรณ์และปรับเปลี่ยนตามพื้นที่โฆษณา เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์/ปรับเปลี่ยนตามพื้นที่โฆษณาจะมอบประสบการณ์การใช้งานที่เพิ่มประสิทธิภาพให้กับผู้ใช้ ไม่ว่าขนาดการแสดงผลจะเป็นอย่างไรก็ตาม ซึ่งช่วยให้แอปของคุณรองรับโทรศัพท์ แท็บเล็ต อุปกรณ์แบบพับได้ อุปกรณ์ ChromeOS การวางแนวแนวตั้งและแนวนอน รวมถึงการกำหนดค่าการแสดงผลที่ปรับขนาดได้ เช่น โหมดแยกหน้าจอและการแสดงหน้าต่างเดสก์ท็อป
เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์/ปรับเปลี่ยนตามพื้นที่โฆษณาจะเปลี่ยนแปลงตามพื้นที่การแสดงผลที่พร้อมใช้งาน การเปลี่ยนแปลงมีตั้งแต่การปรับเลย์เอาต์เล็กน้อยเพื่อเติมพื้นที่ (การออกแบบที่ปรับเปลี่ยนตามอุปกรณ์) ไปจนถึงการแทนที่เลย์เอาต์หนึ่งด้วยอีกเลย์เอาต์หนึ่งโดยสมบูรณ์ เพื่อให้แอปของคุณรองรับขนาดการแสดงผลต่างๆ ได้ดีที่สุด (การออกแบบที่ปรับเปลี่ยนตามพื้นที่โฆษณา)
Jetpack Compose เป็นชุดเครื่องมือ UI แบบประกาศสิ่งที่ต้องการ จึงเหมาะอย่างยิ่งสำหรับการออกแบบและใช้เลย์เอาต์ที่เปลี่ยนแปลงแบบไดนามิกเพื่อแสดงเนื้อหาแตกต่างกันในขนาดการแสดงผลต่างๆ
ทักษะ Android
ดูใน GitHubทำให้แอปปรับเปลี่ยนตามอุปกรณ์
adaptive ทักษะ Android เพื่ออัปเดต UI ของแอปให้ปรับให้เข้ากับอุปกรณ์และการแสดงผล Android ต่างๆandroid skills add adaptiveระบุการเปลี่ยนแปลงเลย์เอาต์ขนาดใหญ่สำหรับ Composables ระดับเนื้อหาอย่างชัดเจน
Composables ระดับแอปและระดับเนื้อหาจะใช้พื้นที่การแสดงผลทั้งหมดที่แอปของคุณใช้ได้ สำหรับ Composables ประเภทนี้ การเปลี่ยนเลย์เอาต์โดยรวมของแอปในการแสดงผลขนาดใหญ่อาจเป็นเรื่องสมเหตุสมผล
หลีกเลี่ยงการใช้ค่าฮาร์ดแวร์จริงในการตัดสินใจเกี่ยวกับเลย์เอาต์ คุณอาจอยากตัดสินใจโดยอิงตามค่าที่จับต้องได้แบบคงที่ (อุปกรณ์เป็นแท็บเล็ตใช่ไหม หน้าจอจริงมีอัตราส่วนกว้างยาวที่แน่นอนใช่ไหม) แต่คำตอบของคำถามเหล่านี้อาจไม่เป็นประโยชน์ในการกำหนดพื้นที่ที่ UI ของคุณใช้ได้
ในแท็บเล็ต แอปอาจทำงานในโหมดหลายหน้าต่าง ซึ่งหมายความว่าแอปอาจแบ่งหน้าจอร่วมกับแอปอื่น ในโหมดการแสดงหน้าต่างเดสก์ท็อปหรือใน ChromeOS แอปอาจอยู่ในหน้าต่างที่ปรับขนาดได้ และอาจมีหน้าจอจริงมากกว่า 1 หน้าจอ เช่น ในอุปกรณ์แบบพับได้ ในกรณีเหล่านี้ทั้งหมด ขนาดหน้าจอจริงไม่เกี่ยวข้องกับการตัดสินใจว่าจะแสดงเนื้อหาอย่างไร
ให้ตัดสินใจโดยอิงตามส่วนของหน้าจอจริงที่จัดสรรให้กับ แอปของคุณ ซึ่งอธิบายโดยเมตริกหน้าต่างปัจจุบันที่ไลบรารี Jetpack WindowManager ให้ไว้ ดูตัวอย่างวิธีใช้ WindowManager ในแอป Compose ได้ที่ตัวอย่าง JetNews
การทำให้เลย์เอาต์ปรับให้เข้ากับพื้นที่การแสดงผลที่พร้อมใช้งานยังช่วยลดปริมาณการจัดการพิเศษที่จำเป็นในการรองรับแพลตฟอร์มอย่าง ChromeOS และรูปแบบของอุปกรณ์อย่างแท็บเล็ตและอุปกรณ์แบบพับได้ด้วย
เมื่อกำหนดเมตริกของพื้นที่ที่แอปของคุณใช้ได้แล้ว ให้แปลง ขนาดดิบเป็นคลาสขนาดหน้าต่างตามที่อธิบายไว้ในหัวข้อใช้คลาสขนาดหน้าต่าง คลาสขนาดหน้าต่างเป็นเบรกพอยต์ที่ออกแบบมาเพื่อสร้างสมดุลระหว่างความเรียบง่ายของตรรกะของแอปกับความยืดหยุ่นในการเพิ่มประสิทธิภาพแอปสำหรับขนาดการแสดงผลส่วนใหญ่
คลาสขนาดหน้าต่างหมายถึงหน้าต่างโดยรวมของแอป ดังนั้นให้ใช้คลาสสำหรับการตัดสินใจเกี่ยวกับเลย์เอาต์ที่จะส่งผลต่อเลย์เอาต์โดยรวมของแอป คุณสามารถส่งคลาสขนาดหน้าต่างลงไปเป็นสถานะ หรือใช้ตรรกะเพิ่มเติมเพื่อสร้างสถานะที่ได้มาเพื่อส่งลงไปใน Composables ที่ซ้อนกัน
@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, /* ... */ ) }
แนวทางแบบเลเยอร์จะจำกัดตรรกะขนาดการแสดงผลไว้ในตำแหน่งเดียวแทนที่จะกระจายไปทั่วแอปในหลายๆ ที่ที่ต้องซิงค์กัน ตำแหน่งเดียวจะสร้างสถานะ ซึ่งสามารถส่งลงไปใน Composables อื่นๆ ได้อย่างชัดเจน เช่นเดียวกับสถานะแอปอื่นๆ การส่งสถานะลงไปอย่างชัดเจนจะทำให้ Composables แต่ละรายการง่ายขึ้น เนื่องจาก Composables จะใช้คลาสขนาดหน้าต่างหรือการกำหนดค่าที่ระบุพร้อมกับข้อมูลอื่นๆ
Composables ที่ซ้อนกันแบบยืดหยุ่นสามารถใช้ซ้ำได้
Composables จะใช้ซ้ำได้มากขึ้นเมื่อวางไว้ในตำแหน่งที่หลากหลายได้ หากต้องวาง Composable ในตำแหน่งที่เฉพาะเจาะจงด้วยขนาดที่เฉพาะเจาะจง ก็เป็นไปได้ยากที่ Composable จะใช้ซ้ำได้ในบริบทอื่นๆ ซึ่งหมายความว่า Composables แต่ละรายการที่ใช้ซ้ำได้ควรหลีกเลี่ยงการขึ้นอยู่กับข้อมูลขนาดการแสดงผล ส่วนกลาง โดยนัย
ลองนึกภาพ Composable ที่ซ้อนกันซึ่งใช้เลย์เอาต์รายละเอียดรายการ ซึ่งอาจแสดงบานหน้าต่างเดียวหรือ 2 บานหน้าต่างข้างกัน
การตัดสินใจเกี่ยวกับรายละเอียดรายการควรเป็นส่วนหนึ่งของเลย์เอาต์โดยรวมของแอป ดังนั้นการตัดสินใจจึงส่งลงมาจาก Composable ระดับเนื้อหา
@Composable fun AdaptivePane( showOnePane: Boolean, /* ... */ ) { if (showOnePane) { OnePane(/* ... */) } else { TwoPane(/* ... */) } }
จะเกิดอะไรขึ้นหากคุณต้องการให้ Composable เปลี่ยนเลย์เอาต์อย่างอิสระโดยอิงตามพื้นที่การแสดงผลที่พร้อมใช้งาน เช่น การ์ดที่แสดงรายละเอียดเพิ่มเติมหากมีพื้นที่ คุณต้องการใช้ตรรกะบางอย่างโดยอิงตามขนาดการแสดงผลที่พร้อมใช้งาน แต่ขนาดใดกันแน่
หลีกเลี่ยงการพยายามใช้ขนาดหน้าจอจริงของอุปกรณ์ วิธีนี้จะไม่ถูกต้องสำหรับหน้าจอประเภทต่างๆ และจะไม่ถูกต้องหากแอปไม่แสดงแบบเต็มหน้าจอ
เนื่องจาก Composable ไม่ใช่ Composable ระดับเนื้อหา จึงไม่ควรใช้เมตริกหน้าต่างปัจจุบันโดยตรง
หากวางคอมโพเนนต์โดยมีระยะห่างจากขอบ (เช่น โดยใช้ระยะขอบภายใน) หรือหากแอปมีคอมโพเนนต์ เช่น แถบนำทางหรือแถบแอป ปริมาณพื้นที่การแสดงผลที่ Composable ใช้ได้อาจแตกต่างกันอย่างมากจากพื้นที่โดยรวมที่แอปใช้ได้
ใช้ความกว้างที่กำหนดให้กับ Composable จริงๆ เพื่อแสดงผล คุณมี 2 ตัวเลือกในการรับความกว้างดังกล่าว
หากต้องการเปลี่ยน ตำแหน่ง หรือ วิธี แสดงเนื้อหา ให้ใช้ คอลเล็กชันตัวปรับแต่งหรือเลย์เอาต์ที่กำหนดเอง เพื่อทำให้เลย์เอาต์ ปรับเปลี่ยนตามอุปกรณ์ วิธีนี้อาจง่ายเพียงแค่ให้องค์ประกอบย่อยเติมพื้นที่ที่พร้อมใช้งานทั้งหมด หรือจัดวางองค์ประกอบย่อยด้วยหลายคอลัมน์หากมีพื้นที่เพียงพอ
หากต้องการเปลี่ยน สิ่งที่ คุณแสดง ให้ใช้
BoxWithConstraintsซึ่งเป็นตัวเลือกที่ ทรงพลังกว่าBoxWithConstraintsมี ข้อจำกัดในการวัดที่คุณใช้เรียก Composables ต่างๆ ได้โดยอิงตาม พื้นที่การแสดงผลที่พร้อมใช้งาน อย่างไรก็ตาม วิธีนี้มีข้อเสียอยู่บ้าง เนื่องจากBoxWithConstraintsจะเลื่อนการคอมโพสิชันออกไปจนกว่าจะถึงระยะเลย์เอาต์ ซึ่งเป็นเวลาที่ทราบข้อจำกัดเหล่านี้แล้ว ทำให้ต้องทำงานมากขึ้นในระหว่างเลย์เอาต์
@Composable fun Card(/* ... */) { BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(/* ... */) Title(/* ... */) } } else { Row { Column { Title(/* ... */) Description(/* ... */) } Image(/* ... */) } } } }
ทำให้ข้อมูลทั้งหมดพร้อมใช้งานสำหรับขนาดการแสดงผลต่างๆ
เมื่อใช้ Composable ที่ใช้ประโยชน์จากพื้นที่การแสดงผลเพิ่มเติม คุณอาจอยากใช้ข้อมูลอย่างมีประสิทธิภาพและโหลดข้อมูลเป็นผลข้างเคียงของขนาดการแสดงผลปัจจุบัน
อย่างไรก็ตาม การทำเช่นนี้ขัดต่อหลักการของโฟลว์ข้อมูลแบบทิศทางเดียว ซึ่งข้อมูลสามารถยกขึ้นและส่งไปยัง Composables เพื่อแสดงผลได้อย่างเหมาะสม ควรส่งข้อมูลไปยัง 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 เป็นแอปที่ใช้เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์เพื่อ รองรับขนาดการแสดงผลต่างๆ
วิดีโอ