מעבר מ-Material 2 ל-Material 3 ב-Compose (כתיבה)

Material Design 3 הוא הדור הבא של Material Design. הוא כולל עיצוב, רכיבים ותכונות של התאמה אישית של Material You, כמו צבע דינמי, שעודכנו. זהו עדכון ל-Material Design 2, והוא תואם לסגנון החזותי החדש ולממשק המשתמש של המערכת ב-Android 12 ואילך.

המדריך הזה מתמקד בהעברה מספריית Jetpack של Compose Material‏ (androidx.compose.material) לספריית Jetpack של Compose Material 3‏ (androidx.compose.material3).

גישות

באופן כללי, לא מומלץ להשתמש גם ב-M2 וגם ב-M3 באפליקציה אחת לטווח ארוך. הסיבה לכך היא ששתי מערכות העיצוב והספריות הרלוונטיות שונות באופן משמעותי מבחינת עיצובי ה-UX/UI והטמעות Compose.

יכול להיות שהאפליקציה שלכם תשתמש במערכת עיצוב, כמו מערכת שנוצרה באמצעות Figma. במקרים כאלה, מומלץ מאוד גם לכם או לצוות העיצוב שלכם להעביר את הנכס מ-M2 ל-M3 לפני שמתחילים את ההעברה ל-Compose. לא הגיוני להעביר אפליקציה ל-M3 אם עיצוב חוויית המשתמש או ממשק המשתמש שלה מבוסס על M2.

בנוסף, הגישה שלכם להעברה צריכה להשתנות בהתאם לגודל, למורכבות ולעיצוב של האפליקציה. כך תוכלו לצמצם את ההשפעה על קוד הבסיס. מומלץ לבצע את ההעברה בשלבים.

מתי כדאי לבצע את ההעברה

מומלץ להתחיל את ההעברה בהקדם האפשרי. עם זאת, חשוב לבדוק אם האפליקציה שלכם מוכנה לחלוטין לעבור מ-M2 ל-M3. יש כמה תרחישים חסימה שכדאי לבדוק לפני שמתחילים:

תרחיש הגישה המומלצת
ללא חסימות התחלת העברה בשלבים
רכיב מ-M2 עדיין לא זמין ב-M3. מידע נוסף זמין בקטע רכיבים ותצוגות בהמשך. התחלת העברה בשלבים
אתם או צוות העיצוב שלכם לא העברתם את מערכת העיצוב של האפליקציה מ-M2 ל-M3 העברת מערכת העיצוב מ-M2 ל-M3, ואז התחלת העברה מדורגת

גם אם אתם מושפעים מהתרחישים שלמעלה, כדאי שתבחרו בגישה הדרגתית להעברה לפני שאתם מבצעים התחייבות ומפיצים עדכון לאפליקציה. במקרים כאלה, צריך להשתמש ב-M2 וב-M3 במקביל, ולהפסיק בהדרגה את השימוש ב-M2 בזמן ההעברה ל-M3.

גישה בשלבים

השלבים הכלליים להעברה בשלבים הם:

  1. מוסיפים תלות ב-M3 לצד תלות ב-M2.
  2. מוסיפים גרסאות M3 של העיצובים של האפליקציה לצד גרסאות M2 של העיצובים של האפליקציה.
  3. העברה של מודולים, מסכים או רכיבים מורכבים נפרדים ל-M3, בהתאם לגודל ולמורכבות של האפליקציה (פרטים מופיעים בקטעים הבאים).
  4. בסיום ההעברה, מסירים את הגרסאות M2 של העיצובים של האפליקציה.
  5. מסירים את התלות ב-M2.

יחסי תלות

ל-M3 יש חבילה וגרסה נפרדים מ-M2:

M2

implementation "androidx.compose.material:material:$m2-version"

M3

implementation "androidx.compose.material3:material3:$m3-version"

הגרסאות העדכניות ביותר של M3 מפורטות בדף הגרסאות של Compose Material 3.

יחסי התלות האחרים של Material מחוץ לספריות הראשיות M2 ו-M3 לא השתנו. הם משתמשים בשילוב של החבילות והגרסאות של M2 ו-M3, אבל אין לכך השפעה על ההעברה. אפשר להשתמש בהם כפי שהם עם M3:

ספרייה חבילה וגרסה
הרכבת סמלי Material androidx.compose.material:material-icons-*:$m2-version
הרכבת Material Ripple androidx.compose.material:material-ripple:$m2-version

ממשקי API ניסיוניים

חלק מממשקי ה-API של M3 נחשבים לניסיוניים. במקרים כאלה, צריך להביע הסכמה ברמת הפונקציה או הקובץ באמצעות ההערה ExperimentalMaterial3Api:

import androidx.compose.material3.ExperimentalMaterial3Api

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppComposable() {
    // M3 composables
}

קביעת עיצוב

גם ב-M2 וגם ב-M3, ה-theme composable נקרא MaterialTheme, אבל החבילות והפרמטרים של הייבוא שונים:

M2

import androidx.compose.material.MaterialTheme

MaterialTheme(
    colors = AppColors,
    typography = AppTypography,
    shapes = AppShapes
) {
    // M2 content
}

M3

import androidx.compose.material3.MaterialTheme

MaterialTheme(
    colorScheme = AppColorScheme,
    typography = AppTypography,
    shapes = AppShapes
) {
    // M3 content
}

צבע

השוואה בין מערכות הצבעים M2 ל-M3
איור 1. מערכת הצבעים M2 (שמאל) לעומת מערכת הצבעים M3 (ימין).

מערכת הצבעים ב-M3 שונה באופן משמעותי מזו של M2. מספר הפרמטרים של הצבע גדל, יש להם שמות שונים והם ממפים באופן שונה לרכיבי M3. ב-Compose, הכלל הזה חל על הכיתה M2‏ Colors, הכיתה M3‏ ColorScheme והפונקציות הקשורות:

M2

import androidx.compose.material.lightColors
import androidx.compose.material.darkColors

val AppLightColors = lightColors(
    // M2 light Color parameters
)
val AppDarkColors = darkColors(
    // M2 dark Color parameters
)
val AppColors = if (darkTheme) {
    AppDarkColors
} else {
    AppLightColors
}

M3

import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme

val AppLightColorScheme = lightColorScheme(
    // M3 light Color parameters
)
val AppDarkColorScheme = darkColorScheme(
    // M3 dark Color parameters
)
val AppColorScheme = if (darkTheme) {
    AppDarkColorScheme
} else {
    AppLightColorScheme
}

בגלל ההבדלים המשמעותיים בין מערכות הצבעים M2 ו-M3, אין מיפוי סביר לפרמטר Color. במקום זאת, אפשר להשתמש בכלי ליצירת נושאים של Material Design כדי ליצור ערכת צבעים מסוג M3. השתמשו בצבעים של M2 כצבעים מרכזיים של המקור בכלי, והכלי ירחיב אותם לצבעים כהים שמשמשים את ערכת הצבעים של M3. מומלץ להשתמש במיפויים הבאים כנקודת התחלה:

M2 Material Theme Builder
primary ראשי
primaryVariant Secondary
secondary Tertiary
surface או background ניטרלי
צבעים מסוג M2 שנעשה בהם שימוש ב-Material Theme Builder ליצירת ערכת צבעים מסוג M3
איור 2. צבעים מסוג M2 של Jetchat ששימשו ב-Material Theme Builder ליצירת ערכת צבעים מסוג M3.

אפשר להעתיק מהכלי את ערכי הקוד הקסדצימלי של הצבעים לעיצוב בהיר ולעיצוב כהה, ולהשתמש בהם כדי להטמיע מופע של M3 ColorScheme. לחלופין, אפשר לייצא קוד Compose באמצעות הכלי ליצירת נושאים של Material.

isLight

בניגוד לכיתה M2 Colors, הכיתה M3 ColorScheme לא כוללת את הפרמטר isLight. באופן כללי, כדאי לנסות ליצור מודל של כל מה שצריך את המידע הזה ברמת העיצוב. לדוגמה:

M2

import androidx.compose.material.lightColors
import androidx.compose.material.darkColors
import androidx.compose.material.MaterialTheme

@Composable
private fun AppTheme(
  darkTheme: Boolean = isSystemInDarkTheme(),
  content: @Composable () -> Unit
) {
  val colors = if (darkTheme) darkColors(…) else lightColors(…)
  MaterialTheme(
      colors = colors,
      content = content
  )
}

@Composable
fun AppComposable() {
    AppTheme {
        val cardElevation = if (MaterialTheme.colors.isLight) 0.dp else 4.dp
        …
    }
}

M3

import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.MaterialTheme

val LocalCardElevation = staticCompositionLocalOf { Dp.Unspecified }
@Composable
private fun AppTheme(
   darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
   val cardElevation = if (darkTheme) 4.dp else 0.dp
    CompositionLocalProvider(LocalCardElevation provides cardElevation) {
        val colorScheme = if (darkTheme) darkColorScheme(…) else lightColorScheme(…)
        MaterialTheme(
            colorScheme = colorScheme,
            content = content
        )
    }
}

@Composable
fun AppComposable() {
    AppTheme {
        val cardElevation = LocalCardElevation.current
        …
    }
}

מידע נוסף זמין במדריך בנושא מערכות עיצוב בהתאמה אישית ב-Compose.

צבע דינמי

תכונה חדשה ב-M3 היא צבע דינמי. במקום להשתמש בצבעים מותאמים אישית, ב-M3 ColorScheme אפשר להשתמש בצבעים של טפט המכשיר ב-Android מגרסה 12 ואילך, באמצעות הפונקציות הבאות:

טיפוגרפיה

השוואה בין מערכות הטיפוגרפיה M2 ו-M3
איור 3. מערכת טיפוגרפיה של M3 (שמאל) לעומת מערכת טיפוגרפיה של M2 (ימין)

מערכת הטיפוגרפיה ב-M3 שונה מזו של M2. מספר הפרמטרים של הגופן הוא בערך זהה, אבל יש להם שמות שונים והם ממפים באופן שונה לרכיבי M3. ב-Compose, הדבר רלוונטי לכיתה M2‏ Typography ולכיתה M3‏ Typography:

M2

import androidx.compose.material.Typography

val AppTypography = Typography(
    // M2 TextStyle parameters
)

M3

import androidx.compose.material3.Typography

val AppTypography = Typography(
    // M3 TextStyle parameters
)

מומלץ להשתמש במיפויי הפרמטרים הבאים של TextStyle כנקודת התחלה:

M2 M3
h1 displayLarge
h2 displayMedium
h3 displaySmall
לא רלוונטי headlineLarge
h4 headlineMedium
h5 headlineSmall
h6 titleLarge
subtitle1 titleMedium
subtitle2 titleSmall
body1 bodyLarge
body2 bodyMedium
caption bodySmall
button labelLarge
לא רלוונטי labelMedium
overline labelSmall

צורה

השוואה בין מערכות צורות M2 ו-M3
איור 4. מערכת צורות M2 (שמאל) לעומת מערכת צורות M3 (ימין)

מערכת הצורות ב-M3 שונה מזו של M2. מספר הפרמטרים של הצורה גדל, השמות שלהם שונים והם ממפים באופן שונה לרכיבי M3. ב-Compose, הכלל הזה חל על הכיתה M2‏ Shapes ועל הכיתה M3‏ Shapes:

M2

import androidx.compose.material.Shapes

val AppShapes = Shapes(
    // M2 Shape parameters
)

M3

import androidx.compose.material3.Shapes

val AppShapes = Shapes(
    // M3 Shape parameters
)

מומלץ להשתמש במיפויי הפרמטרים הבאים של Shape כנקודת התחלה:

M2 M3
לא רלוונטי extraSmall
small small
medium medium
large large
לא רלוונטי extraLarge

רכיבים ופלטפורמות

רוב הרכיבים והפריסות מ-M2 זמינים ב-M3. עם זאת, יש כמה תכונות חסרות וגם תכונות חדשות שלא היו ב-M2. בנוסף, לחלק מהרכיבים ב-M3 יש יותר וריאציות מאשר לרכיבים המקבילים ב-M2. באופן כללי, ממשקי ה-API של M3 דומים ככל האפשר למקבילים הקרובים ביותר שלהם ב-M2.

בגלל המערכות המעודכנות של הצבעים, הגופנים והצורות, רכיבי M3 נוטים למפות באופן שונה לערכי העיצוב החדשים. מומלץ לבדוק את ספריית האסימונים בקוד המקור של Compose Material 3 כמקור האמת של המיפויים האלה.

יש רכיבים שצריך להביא בחשבון שיקולים מיוחדים לגביהם, אבל מומלץ להתחיל עם המיפויים הבאים של הפונקציות:

ממשקי API חסרים:

M2 M3
androidx.compose.material.swipeable עדיין לא זמין

ממשקי API שהוחלפו:

M2 M3
androidx.compose.material.BackdropScaffold אין מקבילה ל-M3, צריך לעבור ל-Scaffold או ל-BottomSheetScaffold במקום זאת
androidx.compose.material.BottomDrawer אין מקבילה ל-M3, צריך לעבור ל-ModalBottomSheet במקום זאת

ממשקי API ששינו שם:

M2 M3
androidx.compose.material.BottomNavigation androidx.compose.material3.NavigationBar
androidx.compose.material.BottomNavigationItem androidx.compose.material3.NavigationBarItem
androidx.compose.material.Chip androidx.compose.material3.AssistChip או androidx.compose.material3.SuggestionChip
androidx.compose.material.ModalBottomSheetLayout androidx.compose.material3.ModalBottomSheet
androidx.compose.material.ModalDrawer androidx.compose.material3.ModalNavigationDrawer

כל ממשקי ה-API האחרים:

M2 M3
androidx.compose.material.AlertDialog androidx.compose.material3.AlertDialog
androidx.compose.material.Badge androidx.compose.material3.Badge
androidx.compose.material.BadgedBox androidx.compose.material3.BadgedBox
androidx.compose.material.BottomAppBar androidx.compose.material3.BottomAppBar
androidx.compose.material.BottomSheetScaffold androidx.compose.material3.BottomSheetScaffold
androidx.compose.material.Button androidx.compose.material3.Button
androidx.compose.material.Card androidx.compose.material3.Card
androidx.compose.material.Checkbox androidx.compose.material3.Checkbox
androidx.compose.material.CircularProgressIndicator androidx.compose.material3.CircularProgressIndicator
androidx.compose.material.Divider androidx.compose.material3.Divider
androidx.compose.material.DropdownMenu androidx.compose.material3.DropdownMenu
androidx.compose.material.DropdownMenuItem androidx.compose.material3.DropdownMenuItem
androidx.compose.material.ExposedDropdownMenuBox androidx.compose.material3.ExposedDropdownMenuBox
androidx.compose.material.ExtendedFloatingActionButton androidx.compose.material3.ExtendedFloatingActionButton
androidx.compose.material.FilterChip androidx.compose.material3.FilterChip
androidx.compose.material.FloatingActionButton androidx.compose.material3.FloatingActionButton
androidx.compose.material.Icon androidx.compose.material3.Icon
androidx.compose.material.IconButton androidx.compose.material3.IconButton
androidx.compose.material.IconToggleButton androidx.compose.material3.IconToggleButton
androidx.compose.material.LeadingIconTab androidx.compose.material3.LeadingIconTab
androidx.compose.material.LinearProgressIndicator androidx.compose.material3.LinearProgressIndicator
androidx.compose.material.ListItem androidx.compose.material3.ListItem
androidx.compose.material.NavigationRail androidx.compose.material3.NavigationRail
androidx.compose.material.NavigationRailItem androidx.compose.material3.NavigationRailItem
androidx.compose.material.OutlinedButton androidx.compose.material3.OutlinedButton
androidx.compose.material.OutlinedTextField androidx.compose.material3.OutlinedTextField
androidx.compose.material.RadioButton androidx.compose.material3.RadioButton
androidx.compose.material.RangeSlider androidx.compose.material3.RangeSlider
androidx.compose.material.Scaffold androidx.compose.material3.Scaffold
androidx.compose.material.ScrollableTabRow androidx.compose.material3.ScrollableTabRow
androidx.compose.material.Slider androidx.compose.material3.Slider
androidx.compose.material.Snackbar androidx.compose.material3.Snackbar
androidx.compose.material.Switch androidx.compose.material3.Switch
androidx.compose.material.Tab androidx.compose.material3.Tab
androidx.compose.material.TabRow androidx.compose.material3.TabRow
androidx.compose.material.Text androidx.compose.material3.Text
androidx.compose.material.TextButton androidx.compose.material3.TextButton
androidx.compose.material.TextField androidx.compose.material3.TextField
androidx.compose.material.TopAppBar androidx.compose.material3.TopAppBar
androidx.compose.material.TriStateCheckbox androidx.compose.material3.TriStateCheckbox

תוכלו למצוא את הרכיבים והפריסות העדכניים ביותר של M3 בסקירה הכללית של Compose Material 3 API, ולעיין בדף הגרסאות כדי למצוא ממשקי API חדשים ומעודכנים.

תצוגת עזר, סרגל צד וחלונית ההזזה לניווט

השוואה בין תבניות M2 ו-M3 עם סרגל סטטוסים ותפריט הניווט
איור 5. תבנית M2 עם סרגל סטטוסים וחלונית הזזה לניווט (שמאל) לעומת תבנית M3 עם סרגל סטטוסים וחלונית הזזה לניווט (ימין).

התשתית ב-M3 שונה מזו של M2. גם ב-M2 וגם ב-M3, הרכיב הראשי של הפריסה נקרא Scaffold, אבל חבילות הייבוא והפרמטרים שונים:

M2

import androidx.compose.material.Scaffold

Scaffold(
    // M2 scaffold parameters
)

M3

import androidx.compose.material3.Scaffold

Scaffold(
    // M3 scaffold parameters
)

המאפיין M2‏ Scaffold מכיל פרמטר backgroundColor שנקרא עכשיו containerColor במאפיין M3‏ Scaffold:

M2

import androidx.compose.material.Scaffold

Scaffold(
    backgroundColor = …,
    content = { … }
)

M3

import androidx.compose.material3.Scaffold

Scaffold(
    containerColor = …,
    content = { … }
)

הכיתה ScaffoldState של M2 לא קיימת יותר ב-M3 כי היא מכילה פרמטר drawerState שכבר לא נדרש. כדי להציג סרגל קטן עם הערך M3 Scaffold, צריך להשתמש במקום זאת ב-SnackbarHostState:

M2

import androidx.compose.material.Scaffold
import androidx.compose.material.rememberScaffoldState

val scaffoldState = rememberScaffoldState()
val scope = rememberCoroutineScope()

Scaffold(
    scaffoldState = scaffoldState,
    content = {
        …
        scope.launch {
            scaffoldState.snackbarHostState.showSnackbar(…)
        }
    }
)

M3

import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()

Scaffold(
    snackbarHost = { SnackbarHost(snackbarHostState) },
    content = {
        …
        scope.launch {
            snackbarHostState.showSnackbar(…)
        }
    }
)

כל הפרמטרים drawer* מ-Scaffold של M2 הוסרו מ-Scaffold של M3. הפרמטרים האלה כוללים פרמטרים כמו drawerShape ו-drawerContent. כדי להציג חלונית הזזה עם Scaffold של M3, צריך להשתמש ברכיב חלונית ההזזה לניווט, כמו ModalNavigationDrawer, במקום זאת:

M2

import androidx.compose.material.DrawerValue
import
import androidx.compose.material.Scaffold
import androidx.compose.material.rememberDrawerState
import androidx.compose.material.rememberScaffoldState

val scaffoldState = rememberScaffoldState(
    drawerState = rememberDrawerState(DrawerValue.Closed)
)
val scope = rememberCoroutineScope()

Scaffold(
    scaffoldState = scaffoldState,
    drawerContent = { … },
    drawerGesturesEnabled = …,
    drawerShape = …,
    drawerElevation = …,
    drawerBackgroundColor = …,
    drawerContentColor = …,
    drawerScrimColor = …,
    content = {
        …
        scope.launch {
            scaffoldState.drawerState.open()
        }
    }
)

M3

import androidx.compose.material3.DrawerValue
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.Scaffold
import androidx.compose.material3.rememberDrawerState

val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()

ModalNavigationDrawer(
    drawerState = drawerState,
    drawerContent = {
        ModalDrawerSheet(
            drawerShape = …,
            drawerTonalElevation = …,
            drawerContainerColor = …,
            drawerContentColor = …,
            content = { … }
        )
    },
    gesturesEnabled = …,
    scrimColor = …,
    content = {
        Scaffold(
            content = {
                …
                scope.launch {
                    drawerState.open()
                }
            }
        )
    }
)

סרגל האפליקציה העליון

השוואה בין תבנית M2 לתבנית M3 עם סרגל האפליקציות העליון ורשימת גלילה
איור 6. תצוגה של תבנית M2 עם סרגל האפליקציות העליון ורשימת פריטים לגלילה (שמאל) לעומת תצוגה של תבנית M3 עם סרגל האפליקציות העליון ורשימת פריטים לגלילה (ימין)

סרגלי האפליקציות העליונים ב-M3 שונים מאלה שב-M2. גם ב-M2 וגם ב-M3, הרכיב הראשי של שורת האפליקציות העליונה נקרא TopAppBar, אבל החבילות והפרמטרים של הייבוא שונים:

M2

import androidx.compose.material.TopAppBar

TopAppBar(…)

M3

import androidx.compose.material3.TopAppBar

TopAppBar(…)

אם בעבר הרכזתם את התוכן ב-M2 TopAppBar, כדאי להשתמש ב-M3 CenterAlignedTopAppBar. כדאי גם לדעת על MediumTopAppBar ו-LargeTopAppBar.

סרגי האפליקציות העליונים של M3 מכילים פרמטר scrollBehavior חדש שמספק פונקציונליות שונה בזמן גלילה בכיתה TopAppBarScrollBehavior, כמו שינוי הגובה. התכונה הזו פועלת בשילוב עם גלילה בתוכן באמצעות Modifer.nestedScroll. אפשר היה לעשות זאת ב-M2 TopAppBar על ידי שינוי ידני של הפרמטר elevation:

M2

import androidx.compose.material.AppBarDefaults
import androidx.compose.material.Scaffold
import androidx.compose.material.TopAppBar

val state = rememberLazyListState()
val isAtTop by remember {
    derivedStateOf {
        state.firstVisibleItemIndex == 0 && state.firstVisibleItemScrollOffset == 0
    }
}

Scaffold(
    topBar = {
        TopAppBar(
            elevation = if (isAtTop) {
                0.dp
            } else {
                AppBarDefaults.TopAppBarElevation
            },
            …
        )
    },
    content = {
        LazyColumn(state = state) { … }
    }
)

M3

import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults

val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()

Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        TopAppBar(
            scrollBehavior = scrollBehavior,
            …
        )
    },
    content = {
        LazyColumn { … }
    }
)

סרגל הניווט / סרגל הניווט התחתון

השוואה בין סרגל הניווט התחתון של M2 לבין סרגל הניווט של M3
איור 7. סרגל הניווט התחתון של M2 (שמאל) לעומת סרגל הניווט של M3 (ימין).

סרגל הניווט התחתון בגרסה M2 נקרא עכשיו סרגל הניווט בגרסה M3. ב-M2 יש את ה-composables‏ BottomNavigation ו-BottomNavigationItem, וב-M3 יש את ה-composables‏ NavigationBar ו-NavigationBarItem:

M2

import androidx.compose.material.BottomNavigation
import androidx.compose.material.BottomNavigationItem

BottomNavigation {
    BottomNavigationItem(…)
    BottomNavigationItem(…)
    BottomNavigationItem(…)
}

M3

import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem

NavigationBar {
    NavigationBarItem(…)
    NavigationBarItem(…)
    NavigationBarItem(…)
}

לחצנים, לחצני סמלים ולחצני FAB

השוואה בין הלחצנים M2 ו-M3
איור 8. לחצני M2 (שמאל) לעומת לחצני M3 (ימין)

לחצנים, לחצני סמלים ולחצני פעולה צפים (FAB) ב-M3 שונים מאלה שב-M2. M3 כולל את כל הרכיבים הניתנים לקישור של לחצן M2:

M2

import androidx.compose.material.Button
import androidx.compose.material.ExtendedFloatingActionButton
import androidx.compose.material.FloatingActionButton
import androidx.compose.material.IconButton
import androidx.compose.material.IconToggleButton
import androidx.compose.material.OutlinedButton
import androidx.compose.material.TextButton

// M2 buttons
Button(…)
OutlinedButton(…)
TextButton(…)
// M2 icon buttons
IconButton(…)
IconToggleButton(…)
// M2 FABs
FloatingActionButton(…)
ExtendedFloatingActionButton(…)

M3

import androidx.compose.material3.Button
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconToggleButton
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.TextButton

// M3 buttons
Button(…)
OutlinedButton(…)
TextButton(…)
// M3 icon buttons
IconButton(…)
IconToggleButton(…)
// M3 FABs
FloatingActionButton(…)
ExtendedFloatingActionButton(…)

גרסה M3 כוללת גם וריאציות חדשות של לחצנים. אפשר לקרוא עליהם במאמר סקירה כללית על ה-API של Compose Material 3.

מעבר

השוואה בין מתגים מסוג M2 לבין מתגים מסוג M3
איור 9. מתג M2 (שמאל) לעומת מתג M3 (ימין).

Switch ב-M3 שונה מ-M2. גם ב-M2 וגם ב-M3, ה-switch composable נקרא Switch, אבל חבילות הייבוא שונות:

M2

import androidx.compose.material.Switch

Switch(…)

M3

import androidx.compose.material3.Switch

Switch(…)

משטחים וגובה

השוואה בין גובה פני השטח של M2 לבין גובה פני השטח של M3 בעיצוב בהיר ובעיצוב כהה
איור 10. גובה פני השטח של M2 לעומת גובה פני השטח של M3 בעיצוב בהיר (משמאל) ובעיצוב כהה (ימין).

המערכות של פני השטח והגובה ב-M3 שונות מאלה של M2. יש שני סוגים של גובה ב-M3:

  • גובה הצל (הצל מוטבע, כמו M2)
  • שיפור טונלי (שכבת-על של צבע, חדש ב-M3)

ב-Compose, הדבר חל על הפונקציה M2‏ Surface ועל הפונקציה M3‏ Surface:

M2

import androidx.compose.material.Surface

Surface(
    elevation = …
) { … }

M3

import androidx.compose.material3.Surface

Surface(
    shadowElevation = …,
    tonalElevation = …
) { … }

אפשר להשתמש בערכים של elevation Dp ב-M2 גם עבור shadowElevation וגם עבור tonalElevation ב-M3, בהתאם להעדפת העיצוב של חוויית המשתמש או ממשק המשתמש. Surface הוא הרכיב המורכב התומך שמאחורי רוב הרכיבים, כך שרכיבים מורכבים של רכיבים עשויים לחשוף גם פרמטרים של גובה שצריך להעביר באותו אופן.

התכונה 'הגברת הטון' ב-M3 מחליפה את הקונספט של שכבות הגבהה בנושאים כהים ב-M2 . כתוצאה מכך, ElevationOverlay ו-LocalElevationOverlay לא קיימים ב-M3, ו-LocalAbsoluteElevation ב-M2 השתנה ל-LocalAbsoluteTonalElevation ב-M3.

הדגשה ואלפא של תוכן

השוואה בין סמל וטקסט של M2 לבין סמל וטקסט של M3
איור 11. סמל M2 והדגשת טקסט (שמאל) לעומת סמל M3 והדגשת טקסט (ימין)

ההדגשה ב-M3 שונה באופן משמעותי מ-M2. ב-M2, ההדגשה כללה שימוש בצבעים על עם ערכי אלפא מסוימים כדי להבדיל בין תוכן כמו טקסט ואייקונים. ב-M3 יש עכשיו כמה גישות שונות:

  • שימוש בצבעים on לצד צבעים variant on ממערכת הצבעים המורחבת M3.
  • שימוש בעוצמות שונות של גופן לטקסט.

כתוצאה מכך, הערכים ContentAlpha ו-LocalContentAlpha לא קיימים ב-M3 וצריך להחליף אותם.

מומלץ להשתמש במיפויים הבאים כנקודת התחלה:

M2 M3
onSurface עם ContentAlpha.high onSurface באופן כללי, FontWeight.MediumFontWeight.Black לטקסט
onSurface עם ContentAlpha.medium onSurfaceVariant באופן כללי, FontWeight.ThinFontWeight.Normal לטקסט
onSurface עם ContentAlpha.disabled onSurface.copy(alpha = 0.38f)

דוגמה להדגשת סמל בגרסה M2 לעומת M3:

M2

import androidx.compose.material.ContentAlpha
import androidx.compose.material.LocalContentAlpha

// High emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.high) {
    Icon(…)
}
// Medium emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
    Icon(…)
}
// Disabled emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) {
    Icon(…)
}

M3

import androidx.compose.material3.LocalContentColor

// High emphasis
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) {
    Icon(…)
}
// Medium emphasis
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurfaceVariant) {
    Icon(…)
}
// Disabled emphasis
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)) {
    Icon(…)
}

ריכזנו כאן דוגמאות להדגשת טקסט ב-M2 וב-M3:

M2

import androidx.compose.material.ContentAlpha
import androidx.compose.material.LocalContentAlpha

// High emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.high) {
    Text(…)
}
// Medium emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
    Text(…)
}
// Disabled emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) {
    Text(…)
}

M3

import androidx.compose.material3.LocalContentColor

// High emphasis
Text(
    …,
    fontWeight = FontWeight.Bold
)
// Medium emphasis
Text(
    …,
    fontWeight = FontWeight.Normal
)
// Disabled emphasis
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)) {
    Text(
        …,
        fontWeight = FontWeight.Normal
    )
}

רקעים ומכולות

הרקעים ב-M2 הם קונטיינרים עם שם ב-M3. באופן כללי, אפשר להחליף את הפרמטרים background* ב-M2 ב-container* ב-M3, באמצעות אותם ערכים. לדוגמה:

M2

Badge(
    backgroundColor = MaterialTheme.colors.primary
) { … }

M3

Badge(
    containerColor = MaterialTheme.colorScheme.primary
) { … }

למידע נוסף על מעבר מ-M2 ל-M3 ב-Compose, תוכלו לעיין במקורות המידע הנוספים הבאים.

Docs

אפליקציות לדוגמה

סרטונים

הפניית API וקוד מקור