Jetpack Compose ช่วยให้การออกแบบและสร้าง UI ของแอปง่ายขึ้นมาก Compose เปลี่ยนสถานะเป็นองค์ประกอบ UI ผ่าน
- การเรียบเรียงองค์ประกอบ
- เลย์เอาต์ขององค์ประกอบ
- การวาดองค์ประกอบ
เอกสารนี้มุ่งเน้นที่เลย์เอาต์ขององค์ประกอบ โดยจะอธิบายบล็อกการสร้างบางอย่างที่ Compose มีให้เพื่อช่วยคุณจัดวางองค์ประกอบ UI
เป้าหมายของเลย์เอาต์ในฟีเจอร์เขียน
การใช้งานระบบเลย์เอาต์ของ Jetpack Compose มีเป้าหมายหลัก 2 ประการ ได้แก่
- ประสิทธิภาพสูง
- ความสามารถในการเขียนเลย์เอาต์ที่กำหนดเองได้อย่างง่ายดาย
ข้อมูลเบื้องต้นเกี่ยวกับฟังก์ชันที่ประกอบกันได้
ฟังก์ชันที่ประกอบได้เป็นองค์ประกอบพื้นฐานของ Compose ฟังก์ชันที่ใช้ร่วมกันได้
คือฟังก์ชันที่ปล่อย Unit
ซึ่งอธิบายส่วนหนึ่งของ UI
ฟังก์ชันจะรับอินพุตบางอย่างและสร้างสิ่งที่แสดงบนหน้าจอ ดูข้อมูลเพิ่มเติมเกี่ยวกับ Composable ได้ในเอกสารประกอบโมเดลความคิดของ Compose
ฟังก์ชันที่ใช้ร่วมกันได้อาจแสดงองค์ประกอบ UI หลายรายการ อย่างไรก็ตาม หากคุณไม่ ให้คำแนะนำเกี่ยวกับวิธีจัดเรียง Compose อาจจัดเรียง องค์ประกอบในลักษณะที่คุณไม่ชอบ ตัวอย่างเช่น โค้ดนี้จะสร้างองค์ประกอบข้อความ 2 รายการ
@Composable fun ArtistCard() { Text("Alfred Sisley") Text("3 minutes ago") }
หากไม่มีคำแนะนำเกี่ยวกับวิธีจัดเรียง Compose จะวางองค์ประกอบข้อความซ้อนกัน ทำให้ข้อความอ่านไม่ได้
Compose มีคอลเล็กชันเลย์เอาต์ที่พร้อมใช้งานเพื่อช่วยคุณจัดเรียงองค์ประกอบ 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
โหนดแรกเป็นโหนดใบ (Leaf Node) จึงรายงานขนาดและแสดงผล วิธีการจัดวางColumn
โหนดจะขอให้Text
โหนดลูกที่ 2 ทำการวัด- โหนด
Text
ที่ 2 เป็นโหนดใบ (Leaf Node) จึงรายงานขนาดและแสดง วิธีการจัดวาง - ตอนนี้โหนด
Column
ได้วัดขนาดและวางตำแหน่งขององค์ประกอบย่อยแล้ว โหนดจึง กำหนดขนาดและตำแหน่งของตัวเองได้ - ตอนนี้โหนดรูท
Row
ได้วัดขนาดและวางตำแหน่งของโหนดลูกแล้ว จึงสามารถกำหนดขนาดและตำแหน่งของตัวเองได้
ประสิทธิภาพ
Compose มีประสิทธิภาพสูงด้วยการวัดเด็กเพียงครั้งเดียว การวัดผลแบบครั้งเดียวเหมาะสําหรับประสิทธิภาพ เนื่องจากช่วยให้ Compose จัดการโครงสร้าง UI ที่ซับซ้อนได้อย่างมีประสิทธิภาพ หากองค์ประกอบวัดองค์ประกอบย่อย 2 ครั้ง และองค์ประกอบย่อยนั้นวัดองค์ประกอบย่อยแต่ละรายการ 2 ครั้ง และอื่นๆ การพยายามจัดวาง UI ทั้งหมดเพียงครั้งเดียวจะต้องทำงานเป็นจำนวนมาก ซึ่งทำให้แอปทำงานได้ยาก
หากเลย์เอาต์ต้องมีการวัดหลายครั้งด้วยเหตุผลบางประการ Compose มี ระบบพิเศษที่เรียกว่าการวัดค่าโดยธรรมชาติ อ่านเพิ่มเติมเกี่ยวกับฟีเจอร์นี้ได้ในการวัดค่าโดยเนื้อแท้ในเลย์เอาต์ Compose
เนื่องจากการวัดและการจัดวางเป็นขั้นตอนย่อยที่แตกต่างกันของ Layout Pass การเปลี่ยนแปลงใดๆ ที่ส่งผลต่อการจัดวางรายการเท่านั้น ไม่ใช่การวัด จึงสามารถดำเนินการแยกกันได้
การใช้ตัวแก้ไขในเลย์เอาต์
ดังที่ได้กล่าวไว้ในตัวแก้ไข Compose คุณสามารถใช้ตัวแก้ไขเพื่อตกแต่งหรือเพิ่มฟังก์ชันให้กับ Composable ได้ ตัวแก้ไขเป็นสิ่งจำเป็น
สำหรับการปรับแต่งเลย์เอาต์ เช่น ในที่นี้เราจะเชื่อมโยงตัวแก้ไขหลายรายการ
เพื่อปรับแต่ง 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
ทำให้ Composable ตอบสนองต่ออินพุตของผู้ใช้และแสดงการกระเพื่อมpadding
จะเว้นที่ว่างรอบองค์ประกอบfillMaxWidth
ทำให้ Composable เติมความกว้างสูงสุดที่ได้รับจาก องค์ประกอบระดับบนsize()
ระบุความกว้างและความสูงที่ต้องการขององค์ประกอบ
เลย์เอาต์ที่เลื่อนได้
ดูข้อมูลเพิ่มเติมเกี่ยวกับเลย์เอาต์ที่เลื่อนได้ในเอกสารประกอบเกี่ยวกับท่าทางสัมผัสในการเขียน
สำหรับรายการและรายการแบบเลื่อน โปรดดูเอกสารประกอบเกี่ยวกับรายการใน Compose
เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์
ควรออกแบบเลย์เอาต์โดยคำนึงถึงการวางแนวหน้าจอและขนาดรูปแบบของอุปกรณ์ที่แตกต่างกัน Compose มีกลไกบางอย่างที่พร้อมใช้งานเพื่อช่วยปรับเลย์เอาต์ที่ประกอบได้ให้เข้ากับการกำหนดค่าหน้าจอต่างๆ
ข้อจำกัด
หากต้องการทราบข้อจำกัดที่มาจากองค์ประกอบระดับบนสุดและออกแบบเลย์เอาต์ตามนั้น คุณสามารถใช้ BoxWithConstraints
ได้ ข้อจำกัด
การวัดผล
อยู่ในขอบเขตของ Lambda เนื้อหา คุณสามารถใช้ข้อจำกัดในการวัดผลเหล่านี้
เพื่อจัดวางเลย์เอาต์ต่างๆ สำหรับการกำหนดค่าหน้าจอที่แตกต่างกันได้
@Composable fun WithConstraintsComposable() { BoxWithConstraints { Text("My minHeight is $minHeight while my maxWidth is $maxWidth") } }
เลย์เอาต์ตามช่อง
Compose มี Composable มากมายที่อิงตาม Material
Design พร้อมด้วยการขึ้นต่อกันของ
androidx.compose.material:material
(รวมอยู่ด้วยเมื่อสร้างโปรเจ็กต์ Compose ใน Android Studio) เพื่อให้การสร้าง UI เป็นเรื่องง่าย โดยมีองค์ประกอบต่างๆ เช่น
Drawer
FloatingActionButton
และ TopAppBar
คอมโพเนนต์ Material ใช้ API ช่อง อย่างมาก ซึ่งเป็นรูปแบบที่ Compose นำมาใช้
เพื่อเพิ่มเลเยอร์การปรับแต่งไว้เหนือ Composable แนวทางนี้ช่วยให้คอมโพเนนต์มีความยืดหยุ่นมากขึ้น เนื่องจากยอมรับองค์ประกอบย่อยที่กำหนดค่าตัวเองได้แทนที่จะต้องแสดงพารามิเตอร์การกำหนดค่าทั้งหมดขององค์ประกอบย่อย
โดยช่องจะเว้นที่ว่างใน UI ไว้ให้นักพัฒนาแอปใส่ข้อมูลตามต้องการ ตัวอย่างเช่น ช่องที่คุณปรับแต่งได้ในTopAppBar
มีดังนี้
โดยปกติแล้ว Composable จะใช้ content
Composable Lambda ( content: @Composable
() -> Unit
) 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