หน้านี้ให้ภาพรวมระดับสูงของเลเยอร์สถาปัตยกรรมที่ประกอบกันเป็น Jetpack Compose และหลักการสำคัญที่ใช้ในการออกแบบนี้
Jetpack Compose ไม่ใช่โปรเจ็กต์แบบโมโนลิธโปรเจ็กต์เดียว แต่สร้างขึ้นจากโมดูลหลายโมดูลที่ประกอบเข้าด้วยกันเพื่อสร้างสแต็กที่สมบูรณ์ การทำความเข้าใจ โมดูลต่างๆ ที่ประกอบกันเป็น Jetpack Compose จะช่วยให้คุณทำสิ่งต่อไปนี้ได้
- ใช้ระดับการแยกข้อมูลที่เหมาะสมเพื่อสร้างแอปหรือไลบรารี
- ทำความเข้าใจเมื่อคุณ "เลื่อนลง" ไปยังระดับที่ต่ำกว่าเพื่อควบคุมหรือปรับแต่งได้มากขึ้น
- ลดทรัพยากร Dependency
เลเยอร์
เลเยอร์หลักของ Jetpack Compose มีดังนี้
รูปที่ 1 เลเยอร์หลักของ Jetpack Compose
เลเยอร์แต่ละเลเยอร์สร้างขึ้นจากระดับล่าง โดยรวมฟังก์ชันการทำงานเพื่อสร้าง คอมโพเนนต์ระดับสูง แต่ละเลเยอร์สร้างขึ้นบน API สาธารณะของเลเยอร์ที่ต่ำกว่า เพื่อยืนยันขอบเขตของโมดูลและช่วยให้คุณแทนที่เลเยอร์ใดก็ได้หาก ต้องการ มาดูเลเยอร์เหล่านี้จากล่างขึ้นบนกัน
- รันไทม์
- โมดูลนี้จะอธิบายพื้นฐานของรันไทม์ Compose เช่น
remembermutableStateOfคำอธิบายประกอบ@ComposableและSideEffectคุณอาจพิจารณาสร้างเลเยอร์นี้โดยตรงหากต้องการเพียงความสามารถในการจัดการทรีของ Compose ไม่ใช่ UI - UI
- เลเยอร์ UI ประกอบด้วยหลายโมดูล (
ui-text,ui-graphics,ui-tooling, ฯลฯ) โมดูลเหล่านี้ใช้พื้นฐานของชุดเครื่องมือ UI เช่นLayoutNode,Modifier, เครื่องจัดการอินพุต เลย์เอาต์ที่กำหนดเอง และการวาด คุณอาจพิจารณาสร้างเลเยอร์นี้หาก ต้องการเพียงแนวคิดพื้นฐานของชุดเครื่องมือ UI - มูลนิธิ
- โมดูลนี้มีบล็อกการสร้าง UI ของ Compose ที่ไม่ขึ้นอยู่กับระบบการออกแบบ
เช่น
RowและColumnLazyColumnการจดจำท่าทางสัมผัสที่เฉพาะเจาะจง ฯลฯ คุณอาจพิจารณาต่อยอดจาก เลเยอร์พื้นฐานเพื่อสร้างระบบการออกแบบของคุณเอง - วัสดุ
- โมดูลนี้มีการใช้งานระบบ Material Design สำหรับ Compose UI ซึ่งมีระบบการกำหนดธีม คอมโพเนนต์ที่มีสไตล์ การระบุการกระเพื่อม และไอคอน สร้างเลเยอร์นี้เมื่อใช้ Material Design ใน แอป
หลักการออกแบบ
หลักการชี้นำสำหรับ Jetpack Compose คือการมอบฟังก์ชันการทำงานขนาดเล็กที่มุ่งเน้น ซึ่งสามารถประกอบ (หรือ Compose) เข้าด้วยกัน แทนที่จะเป็นคอมโพเนนต์แบบโมโนลิธเพียงไม่กี่รายการ แนวทางนี้มีข้อดีหลายประการ
ควบคุม
คอมโพเนนต์ระดับสูงมักจะทำงานให้คุณมากขึ้น แต่จะจำกัดปริมาณการควบคุมโดยตรงที่คุณมี หากต้องการควบคุมเพิ่มเติม คุณสามารถ "เลื่อนลง" เพื่อใช้คอมโพเนนต์ระดับล่างได้
เช่น หากต้องการสร้างภาพเคลื่อนไหวสีของคอมโพเนนต์ คุณอาจใช้
animateColorAsState
API ดังนี้
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
ที่เลเยอร์ Material จัดให้
@Composable fun Button( // … content: @Composable RowScope.() -> Unit ) { Surface(/* … */) { CompositionLocalProvider(/* … */) { // set LocalContentAlpha ProvideTextStyle(MaterialTheme.typography.button) { Row( // … content = content ) } } } }
Button ประกอบด้วย 4 องค์ประกอบ ได้แก่
Material
Surfaceซึ่งมีพื้นหลัง รูปร่าง การจัดการการคลิก ฯลฯA
CompositionLocalProviderซึ่งจะเปลี่ยนอัลฟ่าของเนื้อหาเมื่อเปิดหรือปิดใช้ปุ่มA
ProvideTextStyleกำหนดรูปแบบข้อความเริ่มต้นที่จะใช้Rowระบุนโยบายเลย์เอาต์เริ่มต้นสำหรับเนื้อหาของปุ่ม
เราได้ละเว้นพารามิเตอร์และความคิดเห็นบางส่วนเพื่อให้โครงสร้างชัดเจนยิ่งขึ้น แต่
คอมโพเนนต์ทั้งหมดมีโค้ดเพียงประมาณ 40 บรรทัด เนื่องจากคอมโพเนนต์นี้เพียง
ประกอบคอมโพเนนต์ทั้ง 4 นี้เพื่อใช้ปุ่ม คอมโพเนนต์ต่างๆ เช่น Button
จะมีความคิดเห็นเกี่ยวกับพารามิเตอร์ที่แสดง โดยจะพิจารณาถึงความสมดุลระหว่างการเปิดใช้การปรับแต่งที่กำหนดเองทั่วไป
กับการเพิ่มจำนวนพารามิเตอร์ที่อาจทำให้คอมโพเนนต์
ใช้งานยากขึ้น เช่น คอมโพเนนต์ Material มีการปรับแต่งที่ระบุไว้
ในระบบ Material Design ซึ่งช่วยให้ปฏิบัติตามหลักการ
ออกแบบ Material ได้ง่าย
อย่างไรก็ตาม หากต้องการปรับแต่งนอกเหนือจากพารามิเตอร์ของคอมโพเนนต์
คุณสามารถ "ดร็อปดาวน์" ระดับและแยกคอมโพเนนต์ได้ เช่น Material
Design ระบุว่าปุ่มควรมีพื้นหลังสีทึบ หากต้องการพื้นหลังแบบไล่ระดับสี พารามิเตอร์Button
จะไม่รองรับตัวเลือกนี้ ในกรณีนี้ คุณสามารถใช้การติดตั้งใช้งาน Material Button เป็นข้อมูลอ้างอิงและสร้างคอมโพเนนต์ของคุณเองได้
@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 เกี่ยวกับ
ค่าอัลฟ่าของเนื้อหาปัจจุบัน
และรูปแบบข้อความปัจจุบัน แต่จะแทนที่วัสดุ Surface ด้วย
Row และจัดรูปแบบเพื่อให้ได้ลักษณะที่ต้องการ
หากไม่ต้องการใช้แนวคิดของ 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
- รายการและตารางกริด
- ผลข้างเคียงใน Compose