מעבר מ-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 באותה אפליקציה לטווח ארוך. הסיבה לכך היא ששתי מערכות העיצוב והספריות שלהן שונות מאוד מבחינת עיצוב חוויית המשתמש וממשק המשתמש, וההטמעות שלהן ב-Compose.

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

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

מתי כדאי לעבור

מומלץ להתחיל את המיגרציה בהקדם האפשרי. עם זאת, חשוב לבדוק אם האפליקציה נמצאת במצב שמאפשר לה לבצע מיגרציה מלאה מ-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
מעבר תצוגה עם גלים, לאורך 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, רכיב ה-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 Theme Builder כדי ליצור ערכת צבעים של M3. משתמשים בצבעי M2 כצבעי מקור ליבה בכלי, שהכלי מרחיב לפלטות גוונים שמשמשות את ערכת הצבעים M3. המיפויים הבאים מומלצים כנקודת התחלה:

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

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

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. במצב כתיבה, ההגדרה הזו חלה על המחלקה 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 נועדו להיות דומים ככל האפשר לממשקי ה-API המקבילים הקרובים ביותר ב-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 חדשים ומעודכנים.

Scaffold, snackbars and navigation drawer

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

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

M2

import androidx.compose.material.Scaffold

Scaffold(
    // M2 scaffold parameters
)

M3

import androidx.compose.material3.Scaffold

Scaffold(
    // M3 scaffold parameters
)

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

M2

import androidx.compose.material.Scaffold

Scaffold(
    backgroundColor = ,
    content = {  }
)

M3

import androidx.compose.material3.Scaffold

Scaffold(
    containerColor = ,
    content = {  }
)

הסיווג M2 ScaffoldState כבר לא קיים ב-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* מ-M2 Scaffold הוסרו מ-M3 Scaffold. הם כוללים פרמטרים כמו 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 scaffold with top app bar and scrolled list (left) versus M3 scaffold with top app bar and scrolled list (right)

סרגלי האפליקציות העליונים ב-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, כמו שינוי הגובה. התכונה הזו פועלת בשילוב עם גלילת תוכן באמצעות Modifier.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 יש את רכיבי ה-Composable‏ BottomNavigation ו-BottomNavigationItem, וב-M3 יש את רכיבי ה-Composable‏ 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()
}

כפתורים, כפתורים בצורת סמל וכפתורי פעולה צפים

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

כפתורים, כפתורים עם סמלים וכפתורי פעולה צפים (FAB) ב-M3 שונים מאלה ב-M2. ‫M3 כולל את כל רכיבי ה-Button הניתנים להרכבה של 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, אבל חבילות הייבוא שונות:

M2

import androidx.compose.material.Switch

Switch()

M3

import androidx.compose.material3.Switch

Switch()

פלטפורמות וגובה

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

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

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

בכתיבת אימייל, ההגדרה הזו חלה על הפונקציה 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, כדי להדגיש תוכן כמו טקסט וסמלים, השתמשו בצבעים on עם ערכי אלפא מסוימים. ב-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 וקוד מקור