Material 3 Expressive คือวิวัฒนาการขั้นต่อไปของ Material Design ซึ่งประกอบด้วย การจัดธีม คอมโพเนนต์ และฟีเจอร์การปรับเปลี่ยนในแบบของคุณที่อัปเดตแล้ว เช่น สีแบบเปลี่ยนอัตโนมัติ
คู่มือนี้มุ่งเน้นการย้ายข้อมูลจากไลบรารี Jetpack ของ Wear Compose Material 2.5 (androidx.wear.compose) ไปยังไลบรารี Jetpack ของ Wear Compose Material 3 (androidx.wear.compose.material3) สำหรับแอป
แนวทาง
หากต้องการย้ายข้อมูลโค้ดแอปจาก M2.5 ไปยัง M3 ให้ใช้วิธีเดียวกันกับที่อธิบายไว้ ในคำแนะนำในการย้ายข้อมูล Material Compose สำหรับโทรศัพท์ โดยเฉพาะอย่างยิ่ง
- คุณไม่ควรใช้ทั้ง M2.5 และ M3 ในแอปเดียวในระยะยาว
- คุณไม่ควรใช้ Horologist Composables, Compose Layout หรือ ไลบรารี Compose Material อีกต่อไป แต่ให้ใช้คอมโพเนนต์ใน M3 แทน
- ใช้แนวทางแบบเป็นระยะ
ความสัมพันธ์
M3 มีแพ็กเกจและเวอร์ชันแยกต่างหากจาก M2.5 ดังนี้
M2.5
implementation("androidx.wear.compose:compose-material:1.4.0")
M3
implementation("androidx.wear.compose:compose-material3:1.7.0-alpha04")
ดู Wear Compose เวอร์ชันล่าสุดของ Material 3 ได้ในหน้ารุ่นของ Wear Compose Material 3
ไลบรารี Wear Compose Foundation เวอร์ชัน 1.7.0-alpha04 ได้เปิดตัว คอมโพเนนต์ใหม่บางรายการที่ออกแบบมาให้ทำงานร่วมกับคอมโพเนนต์ Material 3 ในทำนองเดียวกัน SwipeDismissableNavHost จากไลบรารี Wear Compose Navigation ก็มีการ อัปเดตภาพเคลื่อนไหวเมื่อเรียกใช้ใน Wear OS 6 (ระดับ API 36) ขึ้นไป เมื่อ อัปเดตเป็น Wear Compose Material 3 เราขอแนะนำให้อัปเดตไลบรารี Wear Compose Foundation และ Navigation ด้วย
implementation("androidx.wear.compose:compose-foundation:1.7.0-alpha04")
implementation("androidx.wear.compose:compose-navigation:1.7.0-alpha04")
ธีม
ทั้งใน M2.5 และ M3 องค์ประกอบธีมที่ใช้ร่วมกันได้มีชื่อว่า MaterialTheme แต่
แพ็กเกจการนำเข้าและพารามิเตอร์จะแตกต่างกัน ใน M3 เราได้เปลี่ยนชื่อพารามิเตอร์ Colors เป็น ColorScheme และเปิดตัว MotionScheme เพื่อใช้การเปลี่ยน
M2.5
import androidx.wear.compose.material.MaterialTheme
MaterialTheme(
colors = AppColors,
typography = AppTypography,
shapes = AppShapes,
content = content
)
M3
import androidx.wear.compose.material3.MaterialTheme // ... MaterialTheme( colorScheme = ColorScheme(), typography = Typography(), shapes = Shapes(), motionScheme = MotionScheme.standard(), content = { /*content here*/ } )
สี
ระบบสีใน M3 แตกต่างจาก M2.5 อย่างมาก พารามิเตอร์จำนวนสีเพิ่มขึ้น มีชื่อที่แตกต่างกัน และแมปกับคอมโพเนนต์ M3 แตกต่างกัน ใน Compose การตั้งค่านี้จะมีผลกับคลาส M2.5 Colors, คลาส M3
ColorScheme และฟังก์ชันที่เกี่ยวข้อง ดังนี้
M2.5
import androidx.wear.compose.material.Colors
val appColorScheme: Colors = Colors(
// M2.5 Color parameters
)
M3
import androidx.wear.compose.material3.ColorScheme // ... val appColorScheme: ColorScheme = ColorScheme( // M3 ColorScheme parameters )
ตารางต่อไปนี้อธิบายความแตกต่างที่สําคัญระหว่าง M2.5 กับ M3
| M2.5 | M3 |
|---|---|
Color |
เปลี่ยนชื่อเป็น ColorScheme แล้ว |
| 13 สี | 28 สี |
| ไม่มี | การกำหนดธีมสีแบบไดนามิกใหม่ |
| ไม่มี | สีขั้นที่ 3 ใหม่เพื่อการแสดงออกที่มากขึ้น |
การใช้ธีมสีแบบเปลี่ยนอัตโนมัติ
ฟีเจอร์ใหม่ใน M3 คือการกำหนดธีมสีแบบไดนามิก หากผู้ใช้เปลี่ยน สีหน้าปัด สีใน UI จะเปลี่ยนตาม
ใช้ฟังก์ชัน dynamicColorScheme เพื่อใช้รูปแบบสีแบบไดนามิก
และระบุ defaultColorScheme เป็นตัวเลือกสำรองในกรณีที่รูปแบบสีแบบไดนามิก
ไม่พร้อมใช้งาน
@Composable fun myApp() { val dynamicColorScheme = dynamicColorScheme(LocalContext.current) MaterialTheme(colorScheme = dynamicColorScheme ?: myBrandColors) {} } internal val myBrandColors: ColorScheme = ColorScheme( /* Specify colors here */)
การพิมพ์
ระบบการจัดรูปแบบข้อความใน M3 แตกต่างจาก M2.5 และมีฟีเจอร์ต่อไปนี้
- รูปแบบข้อความใหม่ 9 แบบ
- แบบอักษรแบบยืดหยุ่นซึ่งช่วยให้ปรับแต่งสเกลแบบอักษรสำหรับ ความหนา ความกว้าง และความกลมต่างๆ ได้
AnimatedTextซึ่งใช้แบบอักษรแบบยืดหยุ่น
M2.5
import androidx.wear.compose.material.Typography
val Typography = Typography(
// M2.5 TextStyle parameters
)
M3
import androidx.wear.compose.material3.Typography val Typography = Typography( // M3 TextStyle parameters )
แบบอักษร Flex
แบบอักษรยืดหยุ่นช่วยให้นักออกแบบระบุความกว้างและน้ำหนักของแบบอักษรสำหรับขนาดที่เฉพาะเจาะจงได้
รูปแบบข้อความ
TextStyle ต่อไปนี้พร้อมใช้งานใน M3 โดยคอมโพเนนต์ M3 ต่างๆ จะใช้ค่าเหล่านี้โดยค่าเริ่มต้น
| การพิมพ์ | TextStyle |
|---|---|
| Display | displayLarge, displayMedium, displaySmall |
| ชื่อ | titleLarge, titleMedium, titleSmall |
| ป้ายกำกับ | labelLarge, labelMedium, labelSmall |
| ลำตัว | bodyLarge, bodyMedium, bodySmall, bodyExtraSmall |
| ตัวเลข | numeralExtraLarge, numeralLarge, numeralMedium, numeralSmall, numeralExtraSmall |
| Arc | arcLarge, arcMedium, arcSmall |
รูปร่าง
ระบบรูปร่างใน M3 แตกต่างจาก M2.5 จำนวนพารามิเตอร์รูปร่าง เพิ่มขึ้น มีการตั้งชื่อพารามิเตอร์แตกต่างกัน และมีการแมปกับ คอมโพเนนต์ M3 แตกต่างกัน ขนาดรูปร่างที่พร้อมใช้งานมีดังนี้
- เล็กพิเศษ
- เล็ก
- ปานกลาง
- ใหญ่
- ใหญ่พิเศษ
ใน Compose จะมีผลกับคลาส M2 Shapes และคลาส M3
Shapes ดังนี้
M2.5
import androidx.wear.compose.material.Shapes
val Shapes = Shapes(
// M2.5 Shapes parameters
)
M3
import androidx.wear.compose.material3.Shapes val Shapes = Shapes( // M3 Shapes parameters )
ใช้การแมปพารามิเตอร์รูปร่างจากย้ายข้อมูลจาก Material 2 ไปยัง Material 3 ใน Compose เป็นจุดเริ่มต้น
การเปลี่ยนรูปร่าง
M3 ขอแนะนำการเปลี่ยนรูปร่าง: ตอนนี้รูปร่างจะเปลี่ยนตามการโต้ตอบ
ลักษณะการทำงานของการเปลี่ยนรูปร่างมีให้ใช้งานเป็นรูปแบบต่างๆ ในปุ่มกลม หลายปุ่ม โปรดดูรายการปุ่มที่รองรับการเปลี่ยนรูปร่างต่อไปนี้
| ปุ่ม | ฟังก์ชันการเปลี่ยนรูปร่าง |
|---|---|
IconButton |
IconButtonDefaults.animatedShape จะเคลื่อนไหวปุ่มไอคอนเมื่อกด |
IconToggleButton |
IconToggleButtonDefaults.animatedShape จะเคลื่อนไหวปุ่มเปิด/ปิดไอคอนเมื่อกด และ IconToggleButtonDefaults.variantAnimatedShapes จะเคลื่อนไหวปุ่มเปิด/ปิดไอคอนเมื่อกดและเลือก/ยกเลิกการเลือก |
TextButton |
TextButtonDefaults.animatedShape จะทำให้ปุ่มข้อความเคลื่อนไหวเมื่อกด |
TextToggleButton |
TextToggleButtonDefaults.animatedShapes จะทำให้ปุ่มสลับข้อความเคลื่อนไหวเมื่อกด และ TextToggleButtonDefaults.variantAnimatedShapes จะทำให้ปุ่มสลับข้อความเคลื่อนไหวเมื่อกดและเลือก/ยกเลิกการเลือก |
คอมโพเนนต์และเลย์เอาต์
คอมโพเนนต์และเลย์เอาต์ส่วนใหญ่จาก M2.5 จะพร้อมใช้งานใน M3 อย่างไรก็ตาม คอมโพเนนต์และเลย์เอาต์ M3 บางรายการไม่มีอยู่ใน M2.5 นอกจากนี้ คอมโพเนนต์ M3 บางรายการ ยังมีตัวแปรมากกว่าคอมโพเนนต์ที่เทียบเท่าใน M2.5
แม้ว่าคอมโพเนนต์บางอย่างจะต้องพิจารณาเป็นพิเศษ แต่เราขอแนะนำให้ใช้การแมปฟังก์ชันต่อไปนี้เป็นจุดเริ่มต้น
รายการคอมโพเนนต์ Material 3 ทั้งหมดมีดังนี้
และสุดท้ายคือรายการคอมโพเนนต์ที่เกี่ยวข้องบางส่วนจากไลบรารี Wear Compose Foundation
| Wear Compose Foundation 1.7.0-alpha04 | |
|---|---|
| androidx.wear.compose.foundation.hierarchicalFocusGroup | ใช้เพื่อใส่คำอธิบายประกอบที่ Composable ในแอปพลิเคชัน เพื่อติดตามส่วนที่ใช้งานอยู่ของการจัดองค์ประกอบและประสานงานโฟกัส |
| androidx.wear.compose.foundation.pager.HorizontalPager | เครื่องมือเปลี่ยนหน้าแบบเลื่อนในแนวนอนซึ่งสร้างขึ้นจากคอมโพเนนต์ Compose Foundation พร้อมการเพิ่มประสิทธิภาพเฉพาะ Wear เพื่อปรับปรุงประสิทธิภาพและการปฏิบัติตามหลักเกณฑ์ของ Wear OS |
| androidx.wear.compose.foundation.pager.VerticalPager | เครื่องมือเปลี่ยนหน้าแบบเลื่อนแนวตั้งที่สร้างขึ้นบนคอมโพเนนต์ Compose Foundation พร้อมการเพิ่มประสิทธิภาพเฉพาะ Wear เพื่อปรับปรุงประสิทธิภาพและการปฏิบัติตามหลักเกณฑ์ของ Wear OS |
| androidx.wear.compose.foundation.lazy.TransformingLazyColumn | ใช้แทน ScalingLazyColumn เพื่อเพิ่มเอฟเฟกต์การเปลี่ยนภาพเมื่อเลื่อนไปยังแต่ละรายการได้ |
ปุ่ม
ปุ่มใน M3 แตกต่างจาก M2.5 ชิป M2.5 ถูกแทนที่ด้วย
ปุ่ม การติดตั้งใช้งาน Button จะระบุค่าเริ่มต้นสำหรับ Text
maxLines และ textAlign คุณจะลบล้างค่าเริ่มต้นเหล่านั้นได้ในองค์ประกอบ Text
M2.5
import androidx.wear.compose.material.Chip
//M2.5 Buttons
Chip(...)
CompactChip(...)
Button(...)
M3
//M3 Buttons Button(onClick = { }){} CompactButton(onClick = { }){} IconButton(onClick = { }){} TextButton(onClick = { }){}
นอกจากนี้ M3 ยังมีปุ่มรูปแบบใหม่ด้วย ดูได้ที่ภาพรวมเอกสารอ้างอิง API ของ Compose Material 3
M3 เปิดตัวปุ่มใหม่: EdgeButton EdgeButton มีให้เลือก 4 ขนาด ได้แก่ เล็กมาก เล็ก กลาง และใหญ่ EdgeButton
การติดตั้งใช้งานจะระบุค่าเริ่มต้นสำหรับ maxLines ตามขนาด
ซึ่งปรับแต่งได้
หากคุณใช้ TransformingLazyColumn หรือ ScalingLazyColumn ให้ส่ง EdgeButton ไปยัง ScreenScaffold เพื่อให้เปลี่ยนรูปร่างเมื่อเลื่อนแทนที่จะเพิ่ม EdgeButton เป็นรายการสุดท้ายในรายการ ดูโค้ดต่อไปนี้เพื่อดูวิธีใช้ EdgeButton กับ ScreenScaffold และ TransformingLazyColumn
val state = rememberTransformingLazyColumnState() ScreenScaffold( scrollState = state, contentPadding = rememberResponsiveColumnPadding( first = ColumnItemType.ListHeader ), edgeButton = { EdgeButton( onClick = { } ) { Text(stringResource(R.string.show)) } } ){ contentPadding -> TransformingLazyColumn(state = state, contentPadding = contentPadding,){ // additional code here } }
Scaffold
Scaffold ใน M3 แตกต่างจาก M2.5 ใน M3 AppScaffold และ Composable ใหม่
ScreenScaffold ได้เข้ามาแทนที่ Scaffold แล้ว AppScaffold และ
ScreenScaffold จะวางโครงสร้างของหน้าจอและประสานงานการเปลี่ยนของคอมโพเนนต์ ScrollIndicator และ TimeText
AppScaffold ช่วยให้องค์ประกอบหน้าจอแบบคงที่ เช่น TimeText ยังคงมองเห็นได้
ในระหว่างการเปลี่ยนหน้าในแอป เช่น การปัดเพื่อปิด โดยมีช่องสำหรับ
เนื้อหาแอปพลิเคชันหลัก ซึ่งโดยปกติแล้วจะจัดหาโดยคอมโพเนนต์การนำทาง
เช่น SwipeDismissableNavHost
คุณประกาศ AppScaffold สำหรับกิจกรรมและใช้ ScreenScaffold สำหรับแต่ละหน้าจอ
AppScaffold จะเพิ่มTimeTextคอมโพเนนต์เริ่มต้นลงในหน้าจอ คุณสามารถ
ลบล้างได้หากต้องการปรับแต่งโดยใช้พารามิเตอร์ timeText
M2.5
import androidx.wear.compose.material.Scaffold
Scaffold {...}
M3
AppScaffold { val navController = rememberSwipeDismissableNavController() SwipeDismissableNavHost( navController = navController, startDestination = "message_list" ) { composable("message_list") { MessageList(onMessageClick = { id -> navController.navigate("message_detail/$id") }) } composable("message_detail/{id}") { MessageDetail(id = it.arguments?.getString("id")!!) } } } } // Implementation of one of the screens in the navigation @Composable fun MessageDetail(id: String) { // .. Screen level content goes here val scrollState = rememberTransformingLazyColumnState() val padding = rememberResponsiveColumnPadding( first = ColumnItemType.BodyText ) ScreenScaffold( scrollState = scrollState, contentPadding = padding ) { scaffoldPaddingValues -> // Screen content goes here // ...
หากคุณใช้ HorizontalPager กับ HorizontalPagerIndicator คุณสามารถย้ายข้อมูลไปยัง HorizontalPagerScaffold ได้ HorizontalPagerScaffold อยู่ภายใน AppScaffold AppScaffold และ HorizontalPagerScaffold จะวาง
โครงสร้างของ Pager และประสานงานการเปลี่ยนของคอมโพเนนต์
HorizontalPageIndicator และ TimeText
HorizontalPagerScaffold จะแสดง HorizontalPageIndicator ที่
กึ่งกลางด้านท้ายของหน้าจอโดยค่าเริ่มต้น และประสานงานการแสดงและการซ่อน
TimeText และ HorizontalPageIndicator ตามว่ามีการแบ่งหน้า Pager หรือไม่ ซึ่งจะกำหนดโดย PagerState
นอกจากนี้ยังมีAnimatedPageคอมโพเนนต์ใหม่ ซึ่งจะเคลื่อนไหวหน้าเว็บภายใน
Pager ด้วยเอฟเฟกต์การปรับขนาดและเอฟเฟกต์ Scrim ตามตำแหน่งของหน้าเว็บ
AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) val columnState = rememberTransformingLazyColumnState() val contentPadding = rememberResponsiveColumnPadding( first = ColumnItemType.ListHeader, last = ColumnItemType.BodyText, ) HorizontalPagerScaffold(pagerState = pagerState) { HorizontalPager( state = pagerState, ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold( scrollState = columnState, contentPadding = contentPadding ) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding ) { item { ListHeader( modifier = Modifier.fillMaxWidth() ) { Text(text = "Pager sample") } } item { if (page == 0) { Text(text = "Page #$page. Swipe right") } else{ Text(text = "Page #$page. Swipe left and right") } } } } } } } }
สุดท้าย M3 ได้เปิดตัว VerticalPagerScaffold ซึ่งมีรูปแบบเดียวกับ HorizontalPagerScaffold ดังนี้
AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPagerScaffold(pagerState = pagerState) { VerticalPager( state = pagerState ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold { ///… } } } } }
ตัวยึดตำแหน่ง
API มีการเปลี่ยนแปลงบางอย่างระหว่าง M2.5 กับ M3
Placeholder.PlaceholderDefaults มีตัวแก้ไข 2 รายการดังนี้
Modifier.placeholderซึ่งจะวาดแทนเนื้อหาที่ยังไม่ได้โหลด- เอฟเฟกต์การกะพริบของตัวยึดตำแหน่ง
Modifier.placeholderShimmerซึ่ง แสดงเอฟเฟกต์การกะพริบของตัวยึดตำแหน่งที่ทำงานในลูปภาพเคลื่อนไหวขณะ รอให้ข้อมูลโหลด
ดูการเปลี่ยนแปลงเพิ่มเติมในคอมโพเนนต์ Placeholder ได้ในตารางต่อไปนี้
| M2.5 | M3 |
|---|---|
PlaceholderState.startPlaceholderAnimation |
ถูกนำออกแล้ว |
PlaceholderState.placeholderProgression |
ถูกนำออกแล้ว |
PlaceholderState.isShowContent |
เปลี่ยนชื่อเป็น !PlaceholderState.isVisible แล้ว |
PlaceholderState.isWipeOff |
ถูกนำออกแล้ว |
PlaceholderDefaults.painterWithPlaceholderOverlayBackgroundBrush |
ถูกนำออกแล้ว |
PlaceholderDefaults.placeholderBackgroundBrush |
ถูกนำออกแล้ว |
PlaceholderDefaults.placeholderChipColors |
ถูกนำออกแล้ว |
SwipeDismissableNavHost
SwipeDismissableNavHost เป็นส่วนหนึ่งของ wear.compose.navigation เมื่อใช้คอมโพเนนต์นี้กับ M3, MaterialTheme ของ M3 จะอัปเดต LocalSwipeToDismissBackgroundScrimColor และ LocalSwipeToDismissContentScrimColor
TransformingLazyColumn
TransformingLazyColumn เป็นส่วนหนึ่งของ wear.compose.lazy.foundation และเพิ่ม
การรองรับการปรับขนาดและภาพเคลื่อนไหวที่เปลี่ยนรูปร่างในรายการระหว่างการเลื่อน
เพื่อปรับปรุงประสบการณ์ของผู้ใช้ เราขอแนะนำเป็นอย่างยิ่งให้แอปย้ายข้อมูลจาก
ScalingLazyColumn ไปยัง TransformingLazyColumn
เช่นเดียวกับ ScalingLazyColumn ซึ่งมีrememberTransformingLazyColumnState()ให้สร้างTransformingLazyColumnStateที่ระบบจดจำได้ในทุกองค์ประกอบ
หากต้องการเพิ่มภาพเคลื่อนไหวการปรับขนาดและการมอร์ฟ ให้เพิ่มรายการต่อไปนี้ลงในรายการแต่ละรายการ
Modifier.transformedHeightซึ่งช่วยให้คุณคำนวณความสูงที่แปลงแล้วของ รายการโดยใช้TransformationSpecคุณสามารถใช้rememberTransformationSpec()ได้ เว้นแต่คุณต้องการปรับแต่งเพิ่มเติม- A
SurfaceTransformation
หากต้องการยืนยันว่าการเว้นวรรคที่ด้านบนและด้านล่างของรายการถูกต้อง ให้ใช้ตัวแก้ไข minimumVerticalContentPadding
val columnState = rememberTransformingLazyColumnState() val transformationSpec = rememberTransformationSpec() ScreenScaffold( scrollState = columnState ) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding ) { item { ListHeader( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding), transformation = SurfaceTransformation(transformationSpec) ) { Text(text = "Header") } } // ... other items item { Button( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding), transformation = SurfaceTransformation(transformationSpec), onClick = { /* ... */ }, icon = { Icon( imageVector = Icons.Default.Build, contentDescription = "build", ) }, ) { Text( text = "Build", maxLines = 1, overflow = TextOverflow.Ellipsis, ) } } } }
ลิงก์ที่มีประโยชน์
ดูข้อมูลเพิ่มเติมเกี่ยวกับการย้ายข้อมูลจาก M2.5 ไปยัง M3 ใน Compose ได้จากแหล่งข้อมูลเพิ่มเติมต่อไปนี้