หน้านี้จะแสดงภาพรวมระดับสูงของเลเยอร์สถาปัตยกรรมที่ประกอบขึ้นเป็น Jetpack Compose และหลักการหลักที่ส่งผลต่อการออกแบบนี้
Jetpack Compose ไม่ใช่โปรเจ็กต์แบบโมโนลิธิค แต่เป็นโปรเจ็กต์ที่สร้างขึ้นจากโมดูลหลายรายการที่ประกอบเข้าด้วยกันเพื่อสร้างสแต็กที่สมบูรณ์ ทำความเข้าใจเกี่ยวกับโมดูลต่างๆ ที่ประกอบกันเป็น Jetpack Compose จะช่วยให้คุณทําสิ่งต่อไปนี้ได้
- ใช้ระดับการแยกความคิดที่เหมาะสมเพื่อสร้างแอปหรือไลบรารี
- ทําความเข้าใจกรณีที่คุณสามารถ "เลื่อนลง" ไปยังระดับที่ต่ำกว่าเพื่อการควบคุมหรือการปรับแต่งเพิ่มเติม
- ลดจำนวนทรัพยากร Dependency
เลเยอร์
เลเยอร์หลักของ Jetpack Compose มีดังนี้
รูปที่ 1 เลเยอร์หลักของ Jetpack Compose
แต่ละเลเยอร์จะสร้างขึ้นจากระดับที่ต่ำกว่า โดยผสานรวมฟังก์ชันการทำงานเพื่อสร้างคอมโพเนนต์ระดับสูงขึ้น แต่ละเลเยอร์จะสร้างบน API สาธารณะของเลเยอร์ด้านล่าง เพื่อยืนยันขอบเขตของโมดูลและช่วยให้คุณแทนที่เลเยอร์ใดๆ ได้ หากต้องการ มาดูเลเยอร์เหล่านี้จากด้านล่างขึ้นบนกัน
- รันไทม์
- โมดูลนี้จะอธิบายพื้นฐานเกี่ยวกับรันไทม์ Compose เช่น
remember
,mutableStateOf
, หมายเหตุ@Composable
และSideEffect
คุณอาจพิจารณาสร้างเลเยอร์นี้โดยตรงหากต้องการเพียงความสามารถในการจัดการต้นไม้ของ Compose ไม่ใช่ UI ของ Compose - UI
- เลเยอร์ UI ประกอบด้วยโมดูลหลายรายการ (
ui-text
,ui-graphics
,ui-tooling
, ฯลฯ) โมดูลเหล่านี้ใช้พื้นฐานของชุดเครื่องมือ UI เช่นLayoutNode
,Modifier
, ตัวแฮนเดิลอินพุต, เลย์เอาต์ที่กำหนดเอง และการวาด คุณอาจพิจารณาสร้างเลเยอร์นี้ต่อได้หากต้องการแนวคิดพื้นฐานของชุดเครื่องมือ UI เท่านั้น - Foundation
- โมดูลนี้จัดเตรียมบล็อกการสร้างที่แยกจากระบบการออกแบบสำหรับ UI ของ Compose เช่น
Row
และColumn
,LazyColumn
การจดจำท่าทางสัมผัสบางอย่าง เป็นต้น คุณอาจพิจารณาสร้างจากเลเยอร์พื้นฐานเพื่อสร้างระบบการออกแบบของคุณเอง - วัสดุ
- โมดูลนี้นำระบบดีไซน์ Material สำหรับ UI ของ Compose มาใช้ในระบบกำหนดธีม คอมโพเนนต์ที่มีการจัดรูปแบบ การระบุระลอกคลื่น และไอคอน พัฒนาเลเยอร์นี้เมื่อใช้ Material Design ในแอป
หลักการออกแบบ
หลักการที่เป็นหลักสําคัญของ Jetpack Compose คือให้ฟังก์ชันการทํางานเล็กๆ ที่มุ่งเน้นซึ่งสามารถประกอบ (หรือคอมโพซ) เข้าด้วยกันได้ แทนที่จะใช้คอมโพเนนต์แบบโมโนลิธิกเพียงไม่กี่รายการ วิธีการนี้มีข้อดีหลายประการ
ควบคุม
คอมโพเนนต์ระดับสูงขึ้นมักจะทํางานได้มากกว่า แต่จำกัดปริมาณการควบคุมโดยตรงที่คุณมี หากต้องการควบคุมเพิ่มเติม คุณสามารถ "เลื่อนลง" เพื่อใช้คอมโพเนนต์ระดับล่าง
เช่น หากต้องการทำให้สีของคอมโพเนนต์เคลื่อนไหว คุณอาจใช้ animateColorAsState
ดังนี้
val color = animateColorAsState(if (condition) Color.Green else Color.Red)
อย่างไรก็ตาม หากต้องการให้คอมโพเนนต์เริ่มต้นเป็นสีเทาเสมอ คุณจะใช้ API นี้ไม่ได้ แต่คุณสามารถเลื่อนลงเพื่อใช้ API ระดับล่างแทนได้ ดังนี้
Animatable
val color = remember { Animatable(Color.Gray) } LaunchedEffect(condition) { color.animateTo(if (condition) Color.Green else Color.Red) }
API animateColorAsState
ระดับสูงกว่าสร้างขึ้นโดย API ของ Animatable
ระดับต่ำกว่า การใช้ API ระดับล่างจะซับซ้อนกว่าแต่ให้การควบคุมมากกว่า เลือกระดับการแยกแยะข้อมูลให้เหมาะกับความต้องการของคุณมากที่สุด
การปรับแต่ง
การประกอบคอมโพเนนต์ระดับสูงขึ้นจากองค์ประกอบย่อยๆ จะช่วยให้ปรับแต่งคอมโพเนนต์ได้ง่ายขึ้นมากหากจำเป็น ตัวอย่างเช่น ลองดูการใช้งานButton
ที่ได้จากเลเยอร์วัสดุ
@Composable fun Button( // … content: @Composable RowScope.() -> Unit ) { Surface(/* … */) { CompositionLocalProvider(/* … */) { // set LocalContentAlpha ProvideTextStyle(MaterialTheme.typography.button) { Row( // … content = content ) } } } }
Button
ประกอบขึ้นจากองค์ประกอบ 4 อย่าง ได้แก่
วัสดุ
Surface
ที่ให้พื้นหลัง รูปร่าง การจัดการการคลิก ฯลฯA
CompositionLocalProvider
ซึ่งจะเปลี่ยนค่าอัลฟ่าของเนื้อหาเมื่อเปิดหรือปิดใช้ปุ่มA
ProvideTextStyle
ตั้งค่ารูปแบบข้อความเริ่มต้นที่จะใช้Row
จะมีนโยบายเลย์เอาต์เริ่มต้นสำหรับเนื้อหาของปุ่ม
เราได้ละเว้นพารามิเตอร์และความคิดเห็นบางรายการเพื่อให้โครงสร้างชัดเจนยิ่งขึ้น แต่คอมโพเนนต์ทั้งหมดมีโค้ดเพียง 40 บรรทัดเท่านั้น เพราะเป็นการรวมคอมโพเนนต์ทั้ง 4 ส่วนนี้เพื่อใช้งานปุ่ม คอมโพเนนต์อย่าง Button
มีความคิดเห็นเกี่ยวกับพารามิเตอร์ที่แสดง โดยต้องปรับสมดุลระหว่างการเปิดใช้การปรับแต่งทั่วไปกับพารามิเตอร์จำนวนมากที่อาจทําให้คอมโพเนนต์ใช้งานยากขึ้น ตัวอย่างเช่น คอมโพเนนต์ Material มีการปรับแต่งที่ระบุไว้ในระบบ Material Design ซึ่งช่วยให้คุณปฏิบัติตามหลักการของ Material Design ได้อย่างง่ายดาย
อย่างไรก็ตาม หากต้องการปรับแต่งนอกเหนือจากพารามิเตอร์ของคอมโพเนนต์ ให้ "เลื่อนลง" ระดับแล้วแยกคอมโพเนนต์ เช่น Material Design ระบุว่าปุ่มควรมีพื้นหลังสีทึบ หากต้องการพื้นหลังไล่ระดับสี พารามิเตอร์ Button
จะไม่รองรับตัวเลือกนี้ ในกรณีนี้ คุณสามารถใช้การใช้งาน Button
ของ Material เป็นข้อมูลอ้างอิงและสร้างคอมโพเนนต์ของคุณเองได้ ดังนี้
@Composable fun GradientButton( // … background: List<Color>, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Row( // … modifier = modifier .clickable(onClick = {}) .background( Brush.horizontalGradient(background) ) ) { CompositionLocalProvider(/* … */) { // set material LocalContentAlpha ProvideTextStyle(MaterialTheme.typography.button) { content() } } } }
การใช้งานข้างต้นยังคงใช้คอมโพเนนต์จากเลเยอร์ Material เช่น แนวคิดของ Material เกี่ยวกับเนื้อหาปัจจุบันที่เป็นอัลฟ่าและสไตล์ข้อความปัจจุบัน แต่จะใช้ Row
แทนวัสดุ Surface
และจัดรูปแบบเพื่อให้ได้ลักษณะที่ต้องการ
หากไม่ต้องการใช้แนวคิดของ Material เลย เช่น หากต้องการสร้างระบบการออกแบบที่ออกแบบมาเอง คุณก็ใช้คอมโพเนนต์เลเยอร์พื้นฐานได้เพียงอย่างเดียว ดังนี้
@Composable fun BespokeButton( // … backgroundColor: Color, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Row( // … modifier = modifier .clickable(onClick = {}) .background(backgroundColor) ) { // No Material components used content() } }
Jetpack Compose จะสำรองชื่อที่ง่ายที่สุดสำหรับคอมโพเนนต์ระดับสูงสุด เช่น
androidx.compose.material.Text
สร้างขึ้นจาก
androidx.compose.foundation.text.BasicText
วิธีนี้ช่วยให้คุณระบุการใช้งานของคุณเองโดยใช้ชื่อที่ค้นพบได้มากที่สุดได้หากต้องการแทนที่ระดับที่สูงขึ้น
การเลือกการแยกแยะที่เหมาะสม
หลักปรัชญาของ Compose ในการสร้างคอมโพเนนต์แบบเป็นชั้นซึ่งนํากลับมาใช้ซ้ำได้หมายความว่าคุณไม่ควรใช้องค์ประกอบพื้นฐานระดับล่างเสมอไป คอมโพเนนต์ระดับสูงขึ้นจำนวนมากไม่เพียงแต่จะมอบฟังก์ชันการทำงานเพิ่มเติม แต่ยังใช้แนวทางปฏิบัติแนะนำ เช่น การรองรับการช่วยเหลือพิเศษ
ตัวอย่างเช่น หากต้องการเพิ่มการรองรับท่าทางสัมผัสในคอมโพเนนต์ที่กําหนดเอง คุณก็สร้างคอมโพเนนต์นี้ตั้งแต่ต้นได้โดยใช้ Modifier.pointerInput
แต่ก็มีคอมโพเนนต์ระดับสูงขึ้นอื่นๆ ที่สร้างขึ้นจากคอมโพเนนต์นี้ ซึ่งอาจใช้เป็นจุดเริ่มต้นได้ดีกว่า เช่น Modifier.draggable
, Modifier.scrollable
หรือ Modifier.swipeable
โดยทั่วไปแล้ว เราขอแนะนำให้สร้างจากคอมโพเนนต์ระดับสูงสุดซึ่งมีฟังก์ชันการทำงานที่คุณต้องการเพื่อรับประโยชน์จากแนวทางปฏิบัติแนะนำที่รวมอยู่ด้วย
ดูข้อมูลเพิ่มเติม
ดูตัวอย่างการสร้างระบบการออกแบบที่กําหนดเองได้ที่ตัวอย่าง Jetsnack
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- Kotlin สำหรับ Jetpack Compose
- รายการและตารางกริด
- ผลข้างเคียงในโหมดเขียน