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ทำให้ Composable ตอบสนองต่อข้อมูลจากผู้ใช้และแสดง Ripplepaddingเพิ่มพื้นที่ว่างรอบๆ องค์ประกอบfillMaxWidthทำให้ฟังก์ชันที่ประกอบกันได้เติมความกว้างสูงสุดที่ได้รับจากองค์ประกอบระดับบนsize()ระบุความกว้างและความสูงที่ต้องการขององค์ประกอบ
เลย์เอาต์ที่เลื่อนได้
ดูข้อมูลเพิ่มเติมเกี่ยวกับเลย์เอาต์ที่เลื่อนได้ใน เอกสารประกอบเกี่ยวกับท่าทางสัมผัสของ Compose
สำหรับรายการและรายการแบบ Lazy โปรดดูเอกสารประกอบเกี่ยวกับรายการของ Compose
เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์
คุณควรออกแบบเลย์เอาต์โดยคำนึงถึงการวางแนวหน้าจอและขนาดรูปแบบต่างๆ Compose มีกลไกบางอย่างที่พร้อมใช้งานเพื่อช่วยปรับเลย์เอาต์ที่ประกอบกันได้ให้เข้ากับการกำหนดค่าหน้าจอต่างๆ
ข้อจำกัด
หากต้องการทราบข้อจำกัดที่มาจากองค์ประกอบระดับบนและออกแบบเลย์เอาต์ตามนั้น คุณสามารถใช้ BoxWithConstraints ข้อจำกัดด้านการวัดขนาดจะอยู่ในขอบเขตของแลมดาเนื้อหา คุณสามารถใช้ข้อจำกัดด้านการวัดขนาดเหล่านี้เพื่อประกอบเลย์เอาต์ต่างๆ สำหรับการกำหนดค่าหน้าจอต่างๆ ได้ดังนี้
@Composable fun WithConstraintsComposable() { BoxWithConstraints { Text("My minHeight is $minHeight while my maxWidth is $maxWidth") } }
เลย์เอาต์ที่อิงตามสล็อต
Compose มี Composable ที่หลากหลายรายการที่อิงตาม Material
Design พร้อมทรัพยากร Dependency
androidx.compose.material:material (รวมอยู่ด้วยเมื่อสร้าง
โปรเจ็กต์ Compose ใน Android Studio) เพื่อให้การสร้าง UI เป็นเรื่องง่าย โดยมีองค์ประกอบต่างๆ เช่น
Drawer,
FloatingActionButton,
และ TopAppBar
คอมโพเนนต์ Material ใช้ API สล็อต อย่างมาก ซึ่งเป็นรูปแบบที่ Compose นำมาใช้
เพื่อเพิ่มเลเยอร์การปรับแต่งไว้ด้านบนของฟังก์ชันที่ประกอบกันได้ แนวทางนี้ทำให้คอมโพเนนต์มีความยืดหยุ่นมากขึ้น เนื่องจากคอมโพเนนต์ยอมรับองค์ประกอบย่อยที่กำหนดค่าตัวเองได้แทนที่จะต้องเปิดเผยพารามิเตอร์การกำหนดค่าทั้งหมดขององค์ประกอบย่อย
สล็อตจะเว้นพื้นที่ว่างใน UI ไว้ให้นักพัฒนาแอปเติมตามต้องการ ตัวอย่างเช่น สล็อตที่คุณปรับแต่งได้ใน
TopAppBar มีดังนี้
โดยปกติแล้วฟังก์ชันที่ประกอบกันได้จะใช้แลมดา content ที่ประกอบกันได้ ( 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 ปิดอยู่
- ตัวปรับแต่ง Compose
- Kotlin สำหรับ Jetpack Compose
- คอมโพเนนต์และเลย์เอาต์ Material