Jetpack Compose ช่วยให้การออกแบบและสร้าง UI ของแอปง่ายขึ้นมาก Compose จะเปลี่ยนสถานะเป็นองค์ประกอบ UI ผ่าน
- องค์ประกอบขององค์ประกอบ
- เลย์เอาต์ขององค์ประกอบ
- การวาดองค์ประกอบ
เอกสารนี้มุ่งเน้นที่เลย์เอาต์ขององค์ประกอบ โดยอธิบายองค์ประกอบพื้นฐานบางอย่างที่ Compose มีให้เพื่อช่วยคุณวางเลย์เอาต์องค์ประกอบ UI
เป้าหมายของเลย์เอาต์ในช่องการเขียน
การใช้ระบบเลย์เอาต์ของ Jetpack Compose มีเป้าหมายหลัก 2 ประการ ได้แก่
- ประสิทธิภาพสูง
- ความสามารถในการเขียนเลย์เอาต์ที่กำหนดเองได้อย่างง่ายดาย
ข้อมูลเบื้องต้นเกี่ยวกับฟังก์ชันที่ประกอบกันได้
ฟังก์ชันแบบคอมโพสได้คือองค์ประกอบพื้นฐานของ Compose ฟังก์ชันที่คอมโพสิเบิลคือฟังก์ชันที่แสดง Unit
ซึ่งอธิบายส่วนต่างๆ ของ UI ฟังก์ชันจะรับอินพุตบางส่วนและสร้างสิ่งที่แสดงบนหน้าจอ ดูข้อมูลเพิ่มเติมเกี่ยวกับคอมโพสิเบิลได้ที่เอกสารประกอบรูปแบบความคิดของคอมโพสิเบิล
ฟังก์ชันคอมโพสิเบิลอาจแสดงองค์ประกอบ UI หลายรายการ อย่างไรก็ตาม หากคุณไม่ได้ให้คำแนะนำเกี่ยวกับวิธีจัดเรียง เครื่องมือเขียนอาจจัดเรียงองค์ประกอบในลักษณะที่คุณไม่ชอบ ตัวอย่างเช่น โค้ดนี้จะสร้างองค์ประกอบข้อความ 2 รายการ
@Composable fun ArtistCard() { Text("Alfred Sisley") Text("3 minutes ago") }
หากไม่มีคำแนะนำเกี่ยวกับวิธีจัดเรียง เครื่องมือเขียนจะวางองค์ประกอบข้อความซ้อนกัน ทำให้อ่านไม่ได้
เครื่องมือเขียนมีคอลเล็กชันเลย์เอาต์ที่พร้อมใช้งานเพื่อช่วยคุณจัดเรียงองค์ประกอบ UI และช่วยให้คุณกำหนดเลย์เอาต์เฉพาะทางของคุณเองได้ง่าย
คอมโพเนนต์เลย์เอาต์มาตรฐาน
ในหลายกรณี คุณสามารถใช้องค์ประกอบเลย์เอาต์มาตรฐานของ Compose ได้
ใช้ Column
เพื่อวางรายการในแนวตั้งบนหน้าจอ
@Composable fun ArtistCardColumn() { Column { Text("Alfred Sisley") Text("3 minutes ago") } }
ในทำนองเดียวกัน ให้ใช้ Row
เพื่อวางรายการในแนวนอนบนหน้าจอ ทั้ง Column
และ Row
รองรับการกำหนดค่าการจัดแนวขององค์ประกอบที่มี
@Composable fun ArtistCardRow(artist: Artist) { Row(verticalAlignment = Alignment.CenterVertically) { Image(bitmap = artist.image, contentDescription = "Artist image") Column { Text(artist.name) Text(artist.lastSeenOnline) } } }
ใช้ Box
เพื่อวางองค์ประกอบซ้อนกัน นอกจากนี้ Box
ยังรองรับการกำหนดค่าการจัดแนวที่เฉพาะเจาะจงขององค์ประกอบที่มี
@Composable fun ArtistAvatar(artist: Artist) { Box { Image(bitmap = artist.image, contentDescription = "Artist image") Icon(Icons.Filled.Check, contentDescription = "Check mark") } }
บ่อยครั้งที่คุณใช้เพียงองค์ประกอบพื้นฐานเหล่านี้ก็เพียงพอแล้ว คุณสามารถเขียนฟังก์ชันคอมโพสิเบิลของคุณเองเพื่อรวมเลย์เอาต์เหล่านี้เข้าด้วยกันเป็นเลย์เอาต์ที่ซับซ้อนยิ่งขึ้นซึ่งเหมาะกับแอปของคุณ
หากต้องการตั้งค่าตำแหน่งของบุตรหลานภายใน Row
ให้ตั้งค่าอาร์กิวเมนต์ horizontalArrangement
และ
verticalAlignment
สําหรับ Column
ให้ตั้งค่าอาร์กิวเมนต์ verticalArrangement
และ horizontalAlignment
ดังนี้
@Composable fun ArtistCardArrangement(artist: Artist) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.End ) { Image(bitmap = artist.image, contentDescription = "Artist image") Column { /*...*/ } } }
รูปแบบเลย์เอาต์
ในโมเดลเลย์เอาต์ ต้นไม้ UI จะวางในลักษณะที่ผ่านเพียงครั้งเดียว ระบบจะขอให้แต่ละโหนดวัดตัวเองก่อน จากนั้นวัดโหนดย่อยแบบซ้ำซ้อน โดยส่งข้อจำกัดขนาดไปยังโหนดย่อยในต้นไม้ จากนั้นระบบจะปรับขนาดและวางตำแหน่งโหนดใบ โดยส่งขนาดและวิธีการวางตำแหน่งที่แก้ไขแล้วกลับไปยังต้นไม้
กล่าวโดยย่อคือ ผู้ปกครองจะวัดก่อนบุตรหลาน แต่จะได้รับการปรับขนาดและตำแหน่งหลังจากบุตรหลาน
ลองพิจารณาฟังก์ชัน SearchResult
ต่อไปนี้
@Composable fun SearchResult() { Row { Image( // ... ) Column { Text( // ... ) Text( // ... ) } } }
ฟังก์ชันนี้จะแสดงผลเป็นต้นไม้ UI ดังต่อไปนี้
SearchResult
Row
Image
Column
Text
Text
ในตัวอย่าง SearchResult
เลย์เอาต์ต้นไม้ UI จะเป็นไปตามลําดับนี้
- ระบบจะขอให้วัดโหนดรูท
Row
- โหนดรูท
Row
ขอให้โหนดย่อยแรกImage
วัด Image
เป็นโหนดใบ (ไม่มีโหนดย่อย) จึงรายงานขนาดและแสดงวิธีการวาง- โหนดรูท
Row
ขอให้โหนดย่อยลำดับที่ 2 ซึ่งก็คือColumn
วัด - โหนด
Column
ขอให้โหนดText
แรกทำการวัด - โหนด
Text
แรกเป็นโหนดใบ จึงรายงานขนาดและแสดงวิธีการวาง - โหนด
Column
ขอให้โหนดText
ย่อยที่ 2 วัด - โหนด
Text
ที่ 2 เป็นโหนดใบ จึงรายงานขนาดและแสดงวิธีการวาง - เมื่อโหนด
Column
วัดขนาด ปรับขนาด และวางโหนดย่อยแล้ว ก็จะกำหนดขนาดและตำแหน่งของตัวเองได้ - เมื่อโหนดรูท
Row
วัดขนาด กำหนดขนาด และวางโหนดย่อยแล้ว ก็จะกำหนดขนาดและตำแหน่งของตัวเองได้
ประสิทธิภาพ
Compose มีประสิทธิภาพสูงด้วยการวัดองค์ประกอบเพียงครั้งเดียว การวัดผลแบบผ่านครั้งเดียวส่งผลดีต่อประสิทธิภาพ ซึ่งช่วยให้ Compose จัดการต้นไม้ UI ระดับลึกได้อย่างมีประสิทธิภาพ หากองค์ประกอบหนึ่งวัดองค์ประกอบย่อย 2 ครั้ง และองค์ประกอบย่อยนั้นวัดองค์ประกอบย่อยแต่ละรายการ 2 ครั้ง และอื่นๆ การวางเลย์เอาต์ UI ทั้งหมดเพียงครั้งเดียวจะต้องทํางานหลายอย่าง ทำให้แอปมีประสิทธิภาพได้ยาก
หากเลย์เอาต์ต้องใช้การวัดหลายรายการด้วยเหตุผลบางอย่าง Compose มีระบบพิเศษที่เรียกว่าการวัดค่าที่เกี่ยวข้อง อ่านข้อมูลเพิ่มเติมเกี่ยวกับฟีเจอร์นี้ได้ในการวัดค่าที่แท้จริงในเลย์เอาต์ของ Compose
เนื่องจากการวัดผลและตำแหน่งเป็นระยะย่อยที่แตกต่างกันของพาสเลย์เอาต์ คุณจึงทำการเปลี่ยนแปลงที่ส่งผลต่อตำแหน่งของรายการเท่านั้น ไม่ใช่การวัดผลแยกกันได้
การใช้ตัวแก้ไขในเลย์เอาต์
ดังที่ได้กล่าวไว้ในตัวปรับเปลี่ยนการคอมโพสิชัน คุณสามารถใช้ตัวปรับเปลี่ยนเพื่อตกแต่งหรือเพิ่มประสิทธิภาพคอมโพสิชันได้ ตัวแก้ไขเป็นสิ่งจําเป็นในการปรับแต่งเลย์เอาต์ ตัวอย่างเช่น ที่นี่เราใช้ตัวปรับเปลี่ยนหลายรายการเพื่อปรับแต่ง ArtistCard
@Composable fun ArtistCardModifiers( artist: Artist, onClick: () -> Unit ) { val padding = 16.dp Column( Modifier .clickable(onClick = onClick) .padding(padding) .fillMaxWidth() ) { Row(verticalAlignment = Alignment.CenterVertically) { /*...*/ } Spacer(Modifier.size(padding)) Card( elevation = CardDefaults.cardElevation(defaultElevation = 4.dp), ) { /*...*/ } } }
ในโค้ดด้านบน ให้สังเกตการใช้ฟังก์ชันตัวแก้ไขต่างๆ ร่วมกัน
clickable
ทําให้คอมโพสิเบิลตอบสนองต่ออินพุตของผู้ใช้และแสดงภาพกระเพื่อมpadding
เว้นวรรครอบๆ องค์ประกอบfillMaxWidth
ทําให้คอมโพสิเบิลเติมความกว้างสูงสุดที่ได้รับจากส่วนกลางsize()
ระบุความกว้างและความสูงที่ต้องการขององค์ประกอบ
เลย์เอาต์ที่เลื่อนได้
ดูข้อมูลเพิ่มเติมเกี่ยวกับเลย์เอาต์ที่เลื่อนได้ในเอกสารประกอบเกี่ยวกับท่าทางสัมผัสในการเขียน
ดูรายการและรายการแบบเลื่อนในเอกสารประกอบเกี่ยวกับการสร้างรายการ
เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์
เลย์เอาต์ควรออกแบบโดยคำนึงถึงการวางแนวหน้าจอและขนาดรูปแบบของอุปกรณ์ที่แตกต่างกัน Compose มีกลไก 2-3 อย่างพร้อมใช้งานเพื่อช่วยในการปรับเลย์เอาต์แบบคอมโพสิเบิลให้เข้ากับการกำหนดค่าหน้าจอต่างๆ
ข้อจำกัด
คุณสามารถใช้ BoxWithConstraints
เพื่อดูข้อจำกัดที่มาจากองค์ประกอบหลักและออกแบบเลย์เอาต์ให้เหมาะสม ข้อจำกัดในการวัดจะอยู่ในสโคปของ Lambda เนื้อหา คุณสามารถใช้ข้อจำกัดการวัดเหล่านี้เพื่อจัดวางเลย์เอาต์ที่แตกต่างกันสำหรับการกำหนดค่าหน้าจอที่แตกต่างกันได้
@Composable fun WithConstraintsComposable() { BoxWithConstraints { Text("My minHeight is $minHeight while my maxWidth is $maxWidth") } }
เลย์เอาต์ตามช่อง
Compose มีคอมโพสิเบิลที่หลากหลายซึ่งอิงตาม Material Design โดยมีข้อกําหนดของ androidx.compose.material:material
(รวมอยู่เมื่อสร้างโปรเจ็กต์ Compose ใน Android Studio) เพื่อช่วยให้คุณสร้าง UI ได้ง่าย องค์ประกอบต่างๆ เช่น Drawer
, FloatingActionButton
และ TopAppBar
มีให้ใช้งานทั้งหมด
คอมโพเนนต์ Material ใช้ slot API อย่างมาก ซึ่งเป็นรูปแบบที่ Compose นำมาใช้เพื่อเพิ่มการปรับแต่งอีกชั้นบนคอมโพสิเบิล แนวทางนี้ทําให้คอมโพเนนต์มีความยืดหยุ่นมากขึ้น เนื่องจากยอมรับองค์ประกอบย่อยที่กําหนดค่าได้เองแทนที่จะต้องแสดงพารามิเตอร์การกําหนดค่าทั้งหมดขององค์ประกอบย่อย
ช่องจะเว้นพื้นที่ว่างใน UI ไว้เพื่อให้นักพัฒนาแอปกรอกข้อมูลได้ตามต้องการ ตัวอย่างเช่น ต่อไปนี้คือช่องที่คุณปรับแต่งได้ใน TopAppBar
โดยปกติแล้วคอมโพสิเบิลจะใช้ content
composable lambda ( content: @Composable
() -> Unit
) โดย Slot API จะแสดงพารามิเตอร์ content
หลายรายการสําหรับการใช้งานที่เฉพาะเจาะจง
เช่น TopAppBar
ให้คุณระบุเนื้อหาสำหรับ title
,
navigationIcon
และ actions
ตัวอย่างเช่น
Scaffold
ช่วยให้คุณใช้ UI ที่มีโครงสร้างเลย์เอาต์ Material Design พื้นฐานได้
Scaffold
มีช่องสำหรับคอมโพเนนต์ Material ระดับบนสุดที่ใช้กันมากที่สุด
เช่น TopAppBar
,
BottomAppBar
,
FloatingActionButton
และ Drawer
เมื่อใช้ Scaffold
คุณจะตรวจสอบได้ง่ายว่าคอมโพเนนต์เหล่านี้อยู่ในตําแหน่งที่เหมาะสมและทํางานร่วมกันได้อย่างถูกต้อง
@Composable fun HomeScreen(/*...*/) { ModalNavigationDrawer(drawerContent = { /* ... */ }) { Scaffold( topBar = { /*...*/ } ) { contentPadding -> // ... } } }
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ตัวแก้ไขการเขียน
- Kotlin สำหรับ Jetpack Compose
- คอมโพเนนต์และเลย์เอาต์ของ Material Design