Jetpack Compose ช่วยให้การออกแบบและสร้าง UI ของแอปง่ายขึ้นมาก Compose จะแปลงสถานะเป็นองค์ประกอบ UI ผ่านสิ่งต่อไปนี้
- การจัดวางองค์ประกอบ
- เลย์เอาต์ขององค์ประกอบ
- การวาดองค์ประกอบ
เอกสารนี้จะเน้นที่เลย์เอาต์ขององค์ประกอบ โดยอธิบายองค์ประกอบพื้นฐานบางอย่างที่ Compose มีให้เพื่อช่วยคุณจัดวางองค์ประกอบ UI
เป้าหมายของเลย์เอาต์ใน Compose
การใช้งานระบบเลย์เอาต์ของ Jetpack Compose มีเป้าหมายหลัก 2 ประการ ได้แก่
- ประสิทธิภาพสูง
- เขียนเลย์เอาต์ที่กำหนดเองได้อย่างง่ายดาย
ข้อมูลเบื้องต้นเกี่ยวกับฟังก์ชันที่ประกอบกันได้
ฟังก์ชันที่ประกอบกันได้คือองค์ประกอบพื้นฐานของ Compose ฟังก์ชันที่ประกอบกันได้คือฟังก์ชันที่ส่ง Unit ซึ่งอธิบายส่วนหนึ่งของ UI ฟังก์ชันจะรับอินพุตบางอย่างและสร้างสิ่งที่แสดงบนหน้าจอ ดูข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชันที่ประกอบกันได้ในเอกสารประกอบเกี่ยวกับโมเดลความคิดของ 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ขอให้โหนดลูกที่ 2Columnวัดขนาด - โหนด
Columnขอให้โหนดลูกTextแรกวัดขนาด - โหนด
Textแรกเป็นโหนดใบ จึงรายงานขนาดและส่งคำแนะนำในการวางกลับ - โหนด
Columnขอให้โหนดลูกTextที่ 2 วัดขนาด - โหนด
Textที่ 2 เป็นโหนดใบ จึงรายงานขนาดและส่งคำแนะนำในการวางกลับ - เมื่อโหนด
Columnวัดขนาด กำหนดขนาด และวางโหนดลูกแล้ว ก็จะกำหนดขนาดและการวางของตัวเองได้ - เมื่อโหนดราก
Rowวัดขนาด กำหนดขนาด และวางโหนดลูกแล้ว ก็จะกำหนดขนาดและการวางของตัวเองได้
ประสิทธิภาพ
Compose มีประสิทธิภาพสูงด้วยการวัดขนาดของโหนดลูกเพียงครั้งเดียว การวัดขนาดแบบครั้งเดียวเป็นผลดีต่อประสิทธิภาพ ทำให้ Compose จัดการแผนผัง UI ที่ซับซ้อนได้อย่างมีประสิทธิภาพ หากองค์ประกอบหนึ่งวัดขนาดของโหนดลูก 2 ครั้ง และโหนดลูกนั้นวัดขนาดของโหนดลูกแต่ละรายการ 2 ครั้ง และอื่นๆ การพยายามจัดวาง UI ทั้งหมดเพียงครั้งเดียวจะต้องทำงานจำนวนมาก ซึ่งทำให้แอปมีประสิทธิภาพได้ยาก
หากเลย์เอาต์ต้องมีการวัดขนาดหลายครั้งด้วยเหตุผลบางประการ Compose มีระบบพิเศษที่เรียกว่า การวัดขนาดโดยธรรมชาติ คุณอ่านเพิ่มเติมเกี่ยวกับฟีเจอร์นี้ได้ที่ การวัดขนาดโดยธรรมชาติในเลย์เอาต์ 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ทำให้ฟังก์ชันที่ประกอบกันได้ตอบสนองต่อข้อมูลจากผู้ใช้และแสดง Ripplepaddingเพิ่มพื้นที่ว่างรอบๆ องค์ประกอบfillMaxWidthทำให้ฟังก์ชันที่ประกอบกันได้เติมความกว้างสูงสุดที่กำหนดโดยองค์ประกอบแม่size()ระบุความกว้างและความสูงที่ต้องการขององค์ประกอบ
เลย์เอาต์ที่เลื่อนได้
ดูข้อมูลเพิ่มเติมเกี่ยวกับเลย์เอาต์ที่เลื่อนได้ใน เอกสารประกอบเกี่ยวกับท่าทางสัมผัสของ Compose
สำหรับรายการและรายการแบบ Lazy โปรดดูเอกสารประกอบเกี่ยวกับรายการของ Compose
เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์
คุณควรออกแบบเลย์เอาต์โดยคำนึงถึงการวางแนวหน้าจอและขนาดรูปแบบต่างๆ Compose มีกลไก 2-3 อย่างที่พร้อมใช้งานเพื่อช่วยปรับเลย์เอาต์ที่ประกอบกันได้ให้เข้ากับการกำหนดค่าหน้าจอต่างๆ
ข้อจำกัด
หากต้องการทราบข้อจำกัดจากองค์ประกอบแม่และออกแบบเลย์เอาต์ตามนั้น คุณสามารถใช้ BoxWithConstraints ข้อจำกัดในการวัดขนาดจะอยู่ในขอบเขตของแลมดาเนื้อหา คุณสามารถใช้ข้อจำกัดในการวัดขนาดเหล่านี้เพื่อประกอบเลย์เอาต์ต่างๆ สำหรับการกำหนดค่าหน้าจอต่างๆ ได้ดังนี้
@Composable fun WithConstraintsComposable() { BoxWithConstraints { Text("My minHeight is $minHeight while my maxWidth is $maxWidth") } }
เลย์เอาต์ที่อิงตามสล็อต
Compose มีฟังก์ชันที่ประกอบกันได้หลากหลายรายการที่อิงตาม Material
Design พร้อมทรัพยากร Dependency
androidx.compose.material:material (รวมอยู่ด้วยเมื่อสร้าง
โปรเจ็กต์ Compose ใน Android Studio) เพื่อให้การสร้าง UI เป็นเรื่องง่าย โดยมีองค์ประกอบต่างๆ เช่น
Drawer,
FloatingActionButton,
และ TopAppBar
คอมโพเนนต์เนื้อหาใช้ API สล็อต อย่างมาก ซึ่งเป็นรูปแบบที่ Compose นำมาใช้
เพื่อเพิ่มเลเยอร์การปรับแต่งไว้ด้านบนของฟังก์ชันที่ประกอบกันได้ แนวทางนี้ทำให้คอมโพเนนต์มีความยืดหยุ่นมากขึ้น เนื่องจากคอมโพเนนต์ยอมรับองค์ประกอบย่อยที่กำหนดค่าตัวเองได้แทนที่จะต้องเปิดเผยพารามิเตอร์การกำหนดค่าทั้งหมดขององค์ประกอบย่อย
สล็อตจะเว้นพื้นที่ว่างใน UI ไว้ให้นักพัฒนาแอปเติมตามต้องการ ตัวอย่างเช่น สล็อตที่คุณปรับแต่งได้ใน
TopAppBar มีดังนี้
โดยปกติแล้วฟังก์ชันที่ประกอบกันได้จะใช้แลมดา content ที่ประกอบกันได้ ( content: @Composable
() -> Unit) API สล็อตจะเปิดเผยพารามิเตอร์ content หลายรายการสำหรับการใช้งานที่เฉพาะเจาะจง
ตัวอย่างเช่น TopAppBar ช่วยให้คุณระบุเนื้อหาสำหรับ title, navigationIcon และ actions ได้
ตัวอย่างเช่น
Scaffold
ช่วยให้คุณใช้ UI ที่มีโครงสร้างเลย์เอาต์พื้นฐานของ Material Design ได้
Scaffoldมีสล็อตสำหรับคอมโพเนนต์เนื้อหาระดับบนสุดที่ใช้กันมากที่สุด
เช่น TopAppBar,
BottomAppBar,
FloatingActionButton,
และ Drawer การใช้ Scaffold จะช่วยให้มั่นใจได้ว่าคอมโพเนนต์เหล่านี้อยู่ในตำแหน่งที่เหมาะสมและทำงานร่วมกันได้อย่างถูกต้อง
@Composable fun HomeScreen(/*...*/) { ModalNavigationDrawer(drawerContent = { /* ... */ }) { Scaffold( topBar = { /*...*/ } ) { contentPadding -> // ... } } }
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ตัวปรับแต่ง Compose
- Kotlin สำหรับ Jetpack Compose
- คอมโพเนนต์และเลย์เอาต์เนื้อหา