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ทำให้องค์ประกอบตอบสนองต่ออินพุตของผู้ใช้และแสดงระลอกคลื่น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 ใช้ Slot 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