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, פועלים לפי אותה גישה שמתוארת במדריך להעברת חומרים מ-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.8.0-alpha01")
אפשר לראות את הגרסאות האחרונות של M3 בדף הגרסאות של Wear Compose.
בגרסה 1.8.0-alpha01 של ספריית Wear Compose Foundation נוספו כמה רכיבים חדשים שמיועדים לעבודה עם רכיבי 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.8.0-alpha01")
implementation("androidx.wear.compose:compose-navigation:1.8.0-alpha01")
עיצוב
גם ב-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 |
|---|---|
Colors |
השם שונה ל-ColorScheme |
| 13 צבעים | 29 צבעים |
| לא רלוונטי | ערכות נושא חדשות של צבעים דינמיים |
| לא רלוונטי | צבעים שלישוניים חדשים לביטוי מגוון יותר |
עיצוב דינמי של צבעים
תכונה חדשה ב-M3 היא ערכות נושא עם צבעים דינמיים. אם המשתמשים משנים את הצבעים בתצוגת השעון, הצבעים בממשק המשתמש משתנים בהתאם.
אפשר להשתמש בפונקציה 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, והיא כוללת את התכונות הבאות:
- תשעה סגנונות טקסט חדשים
- גופנים גמישים, שמאפשרים התאמה אישית של סולמות הסוגים למשקלים, לרוחבים ולעיגולים שונים
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
גופנים גמישים מאפשרים למעצבים לציין את הרוחב והמשקל של סוג הגופן לגדלים ספציפיים.
סגנונות טקסט
אלה סגנונות הטקסט שזמינים ב-M3. הם מופעלים כברירת מחדל על ידי רכיבים שונים של M3.
| טיפוגרפיה | TextStyle |
|---|---|
| תצוגה | displayLarge, displayMedium, displaySmall |
| כותרת | titleLarge, titleMedium, titleSmall |
| תווית | labelLarge, labelMedium, labelSmall |
| גוף | bodyLarge, bodyMedium, bodySmall, bodyExtraSmall |
| שם מספר | numeralExtraLarge, numeralLarge, numeralMedium, numeralSmall, numeralExtraSmall |
| קשת | arcLarge, arcMedium, arcSmall |
צורה
מערכת הצורות ב-M3 שונה מזו שב-M2.5. מספר הפרמטרים של הצורה גדל, השמות שלהם שונים והמיפוי שלהם לרכיבי M3 שונה. אלה הגדלים של הצורות שזמינים:
- קטן במיוחד
- קטן
- בינוני
- גדול
- גדול במיוחד
במצב כתיבה, ההגדרה הזו רלוונטית למחלקות M2.5 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.animatedShapes מפעיל אנימציה של לחצן הסמל בלחיצה |
IconToggleButton |
IconToggleButtonDefaults.animatedShapes יוצר אנימציה ללחצן ההפעלה/ההשבתה של הסמל בלחיצה ו- IconToggleButtonDefaults.variantAnimatedShapes יוצר אנימציה ללחצן ההפעלה/ההשבתה של הסמל בלחיצה ובסימון/ביטול הסימון |
TextButton |
TextButtonDefaults.animatedShapes מוסיף אנימציה ללחצן הטקסט כשלוחצים עליו |
TextToggleButton |
TextToggleButtonDefaults.animatedShapes מוסיף אנימציה למתג הטקסט כשלוחצים עליו, ו-TextToggleButtonDefaults.variantAnimatedShapes מוסיף אנימציה למתג הטקסט כשלוחצים עליו וכשמסמנים או מבטלים את הסימון שלו. |
רכיבים ופריסה
רוב הרכיבים והפריסות מ-M2.5 זמינים ב-M3. עם זאת, חלק מהרכיבים והפריסות של M3 לא היו קיימים ב-M2.5. בנוסף, לחלק מהרכיבים של M3 יש יותר וריאציות מאשר לרכיבים המקבילים ב-M2.5.
יש רכיבים שצריך להתייחס אליהם באופן מיוחד, אבל כנקודת התחלה מומלץ להשתמש במיפויים הבאים של פונקציות:
ריכזנו כאן רשימה של רכיבים נפוצים של Material 3 והרכיבים המקבילים שלהם ב-Material 2.5:
ולבסוף, רשימה של כמה רכיבים רלוונטיים מהספרייה Wear Compose Foundation:
| Wear Compose Foundation 1.8.0-alpha01 | |
|---|---|
| androidx.wear.compose.foundation.hierarchicalFocusGroup | משמש להוספת הערות לתכנים קומפוזביליים באפליקציה, כדי לעקוב אחרי החלק הפעיל של הקומפוזיציה ולתאם את המיקוד. |
| androidx.wear.compose.foundation.pager.HorizontalPager | רכיב pager עם גלילה אופקית, שמבוסס על רכיבי Compose Foundation עם שיפורים ספציפיים ל-Wear כדי לשפר את הביצועים ולעמוד בהנחיות של Wear OS. |
| androidx.wear.compose.foundation.pager.VerticalPager | רכיב pager עם גלילה אנכית, שמבוסס על רכיבי 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, edgeButton = { EdgeButton( onClick = { }, modifier = Modifier.scrollable( state, orientation = Orientation.Vertical, reverseDirection = true, // Apply overscroll to the EdgeButton for proper scrolling behavior. overscrollEffect = rememberOverscrollEffect(), ), ) { Text(stringResource(R.string.show)) } }, ) { contentPadding -> TransformingLazyColumn(state = state, contentPadding = contentPadding) { // additional code here // ... } }
פיגום
ה-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 transformationSpec = rememberTransformationSpec() ScreenScaffold( scrollState = scrollState, ) { contentPadding -> // Screen content goes here // ...
אם אתם משתמשים ב-HorizontalPager עם HorizontalPageIndicator, אתם יכולים לעבור ל-HorizontalPagerScaffold. HorizontalPagerScaffold מוצב בתוך AppScaffold. הרכיבים AppScaffold ו-HorizontalPagerScaffold מציגים את המבנה של רכיב Pager ומתאמים את המעברים של הרכיבים HorizontalPageIndicator ו-TimeText.
HorizontalPagerScaffold מוצג כברירת מחדל במרכז הקצה של המסך, והוא מתאם את ההצגה וההסתרה של TimeText ושל HorizontalPageIndicator בהתאם לכך שמתבצעת החלפה של דפים ב-Pager. הפעולה הזו נקבעת על ידי PagerState.HorizontalPageIndicator
יש גם רכיב AnimatedPage חדש, שמנפיש דף בתוך רכיב Pager עם אפקט של שינוי גודל ומסך הצללה על סמך המיקום שלו.
AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPagerScaffold(pagerState = pagerState) { HorizontalPager( state = pagerState, flingBehavior = PagerScaffoldDefaults.snapWithSpringFlingBehavior( state = pagerState ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { 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 = "Pager sample") } } item { Card( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding( CardDefaults.minimumVerticalListContentPadding ), transformation = SurfaceTransformation(transformationSpec), ) { if (page == 0) { Text(text = "Page #$page. Swipe right") } else { Text(text = "Page #$page. Swipe left and right") } } } } } } } } }
לבסוף, ב-M3 מוצג VerticalPagerScaffold שפועל לפי אותו דפוס כמו HorizontalPagerScaffold:
@Composable fun VerticalPagerScaffoldSample() { AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPagerScaffold(pagerState = pagerState) { VerticalPager( state = pagerState, flingBehavior = PagerScaffoldDefaults.snapWithSpringFlingBehavior( state = pagerState ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { Text(text = "Page #$page") Spacer(modifier = Modifier.height(8.dp)) Text(text = "Swipe up and down") } } } } } } }
Placeholder
יש כמה שינויים ב-API בין M2.5 ל-M3. M3 כולל שני משני placeholder:
-
Modifier.placeholder, שמוצג במקום תוכן שעדיין לא נטען - אפקט נצנוץ של 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, M3 MaterialTheme מעדכן את LocalSwipeToDismissBackgroundScrimColor ואת LocalSwipeToDismissContentScrimColor.
TransformingLazyColumn
TransformingLazyColumn הוא חלק מ-androidx.wear.compose.foundation.lazy ומוסיף תמיכה בהתאמת גודל ובאנימציות של שינוי צורה בפריטים ברשימה במהלך הגלילה, כדי לשפר את חוויית המשתמש. מומלץ מאוד להעביר את האפליקציות מ-ScalingLazyColumn ל-TransformingLazyColumn.
בדומה ל-ScalingLazyColumn, הוא מספק rememberTransformingLazyColumnState() כדי ליצור TransformingLazyColumnState שנזכר בכל ההודעות.
כדי להוסיף אנימציות של שינוי גודל ושינוי צורה, מוסיפים את הפרטים הבאים לכל פריט ברשימה:
-
Modifier.transformedHeight, שמאפשרת לכם לחשב את הגובה של הפריטים אחרי השינוי באמצעותTransformationSpec, אתם יכולים להשתמש ב-rememberTransformationSpec()אלא אם אתם צריכים התאמה אישית נוספת. -
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, אפשר לעיין במקורות המידע הנוספים הבאים.