Migracja z Material 2 do Material 3 w sekcji Utwórz

Material Design 3 to kolejny etap w ewolucji Material Design. Obejmuje zaktualizowane motywy, komponenty i funkcje personalizacji Material You, takie jak dynamiczne kolory. Aktualizacja Material Design 2 jest zgodna z nowym stylem wizualnym i interfejsem systemu na Androidzie 12 i nowszych wersjach.

Ten przewodnik skupia się na migracji z biblioteki Compose Material (androidx.compose.material) Jetpack do biblioteki Compose Material 3 (androidx.compose.material3) Jetpack,

Podejścia

Ogólnie nie należy używać M2 i M3 w jednej aplikacji długoterminowej. Wynika to z faktu, że 2 systemy projektowe i odpowiadające im biblioteki znacznie się różnią pod względem UX/UI oraz implementacji Compose.

Aplikacja może korzystać z systemu projektowania, np. utworzonego w aplikacji Figma. W takich przypadkach zdecydowanie zalecamy też przeprowadzenie migracji z M2 do M3 przez Ciebie lub zespół projektowy przed rozpoczęciem migracji do tworzenia wiadomości. Migracja aplikacji do M3 nie ma sensu, jeśli jej interfejs/UI jest oparty na M2.

Twoje podejście do migracji powinno się różnić w zależności od rozmiaru aplikacji, jej złożoności oraz UX i projektu interfejsu. Pomaga to zminimalizować wpływ na bazę kodu. Migracja powinna przebiegać stopniowo.

Kiedy przenosić

Rozpocznij migrację jak najszybciej. Ważne jest jednak, aby zastanowić się, czy istnieje realna możliwość pełnej migracji aplikacji z M2 do M3. Istnieje kilka scenariuszy „blokujących”, które warto przeanalizować, zanim zaczniesz:

Scenariusz Zalecane działania
Bez „blokerów” Rozpocznij migrację stopniową
Komponent z wersji M2 nie jest jeszcze dostępny w wersji M3. Zobacz sekcję Komponenty i układy poniżej. Rozpocznij migrację stopniową
Ani Ty, ani Twój zespół projektowy nie przenieśliście systemu projektowania aplikacji z M2 do M3. Przeprowadź migrację systemu projektowania z M2 do M3, a następnie rozpocznij migrację stopniową

Nawet jeśli dotyczy Cię podane wyżej scenariusze, zastosuj stopniowe podejście do migracji przed zatwierdzeniem i opublikowaniem aktualizacji aplikacji. W takich przypadkach należy używać zarówno M2 i M3, jak i M3, a następnie stopniowo wycofywać M2 i przejść na M3.

Metoda stopniowa

Ogólne kroki migracji stopniowej:

  1. Dodaj zależność M3 do zależności M2.
  2. Dodaj wersje M3 motywów aplikacji razem z wersjami M2 motywów aplikacji.
  3. Przenieś poszczególne moduły, ekrany lub elementy kompozycyjne do wersji M3 w zależności od rozmiaru i złożoności aplikacji (szczegóły znajdziesz w sekcjach poniżej).
  4. Po zakończeniu migracji usuń wersje M2 motywów aplikacji.
  5. Usuń zależność M2.

Zależności

M3 ma oddzielny pakiet i wersję do M2:

M2

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

M3

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

Najnowsze wersje M3 znajdziesz na stronie wersji Compose Material 3.

Inne zależności Materiałów poza głównymi bibliotekami M2 i M3 nie uległy zmianie. Wykorzystują one połączenie pakietów oraz wersji M2 i M3, ale nie ma to wpływu na migrację. Można ich używać w niezmienionej formie w M3:

Biblioteka Pakiet i wersja
Ikony Material Material Design androidx.compose.material:material-icons-*:$m2-version
Fabryka materiału kompozycyjnego androidx.compose.material:material-ripple:$m2-version
Klasa rozmiaru okna Compose Material 3 androidx.compose.material3:material3-window-size-class:$m3-version

Eksperymentalne interfejsy API

Niektóre interfejsy API M3 są uznawane za eksperymentalne. W takich przypadkach musisz wyrazić zgodę na poziomie funkcji lub pliku za pomocą adnotacji ExperimentalMaterial3Api:

import androidx.compose.material3.ExperimentalMaterial3Api

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

Motywy

Zarówno w wersji M2, jak i M3 funkcja kompozycyjna motywu nazywa się MaterialTheme, ale pakiety do importu i parametry są inne:

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
}

Kolor

Porównanie systemów kolorów od M2 do M3
Rysunek 1 System kolorów M2 (po lewej) i M3 (po prawej).

System kolorów w M3 znacznie różni się od systemu M2. Wzrosła liczba parametrów koloru, mają one różne nazwy i odmienne są mapowane w inny sposób niż komponenty M3. W narzędziu Compose dotyczy to klasy M2 Colors, klasy M3 ColorScheme i powiązanych funkcji:

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
}

Ze względu na istotne różnice między systemami kolorów M2 i M3 nie ma rozsądnego mapowania parametrów Color. Zamiast tego użyj narzędzia Material Theme Builder, aby wygenerować schemat kolorów M3. Użyj kolorów M2 jako „podstawowych” kolorów źródłowych w narzędziu, które następnie rozwija się w palety tonalne używane w schemacie kolorów M3. Jako punktu wyjścia zalecamy te mapowania:

M2 Kreator motywów Material Design
primary Główny
primaryVariant Secondary
secondary Tertiary
surface lub background Nie mam zdania
Kolory M2 używane w Material Theme Builder do generowania schematu kolorów M3
Rysunek 2. Kolory Jetchata M2 używane w Material Theme Builder do generowania schematu kolorów M3.

Możesz skopiować z tego narzędzia wartości szesnastkowe kolorów dla jasnego i ciemnego motywu i użyć ich do implementacji instancji ColorScheme M3. Kod Compose może też wyeksportować narzędzie Material Theme Builder.

isLight

W przeciwieństwie do klasy Colors M2 klasa ColorScheme M3 nie zawiera parametru isLight. Ogólnie rzecz biorąc, spróbuj modelować potrzebne informacje na poziomie motywu. Na przykład:

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
        …
    }
}

Więcej informacji znajdziesz w przewodniku na temat niestandardowego projektowania systemów w tworzeniu wiadomości.

Kolory dynamiczne

Nową funkcją w wersji M3 jest dynamiczny kolor. Zamiast kolorów niestandardowych na Androidzie 12 i nowszych modelach ColorScheme w M3 M3 może używać tych funkcji:

Typografia

Porównanie systemów typograficznych M2 i M3
Rysunek 3. system typograficzny M3 (po lewej) a system typograficzny M2 (po prawej)

System typograficzny w M3 jest inny niż M2. Liczba parametrów typograficznych jest mniej więcej taka sama, ale mają inne nazwy i inaczej są mapowane na komponenty M3. W narzędziu Compose dotyczy to klasy M2 Typography i klasy 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
)

Na początek zalecamy te mapowania parametrów TextStyle:

M2 M3
h1 displayLarge
h2 displayMedium
h3 displaySmall
Nie dotyczy headlineLarge
h4 headlineMedium
h5 headlineSmall
h6 titleLarge
subtitle1 titleMedium
subtitle2 titleSmall
body1 bodyLarge
body2 bodyMedium
caption bodySmall
button labelLarge
Nie dotyczy labelMedium
overline labelSmall

Kształt

Porównanie systemów kształtu M2 i M3
Rysunek 4. system kształtów M2 (po lewej) a system kształtów M3 (po prawej)

System kształtów w M3 jest inny niż w M2. Wzrosła liczba parametrów kształtu, mają one odmienne nazwy i mapują inaczej na komponenty M3. W narzędziu Compose dotyczy to klasy M2 Shapes i klasy 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
)

Na początek zalecamy te mapowania parametrów Shape:

M2 M3
Nie dotyczy extraSmall
small small
medium medium
large large
Nie dotyczy extraLarge

Komponenty i układy

Większość komponentów i układów z M2 jest dostępna w M3. Jednak niektórych brakuje i są nowe, których nie było w M2. Ponadto niektóre komponenty M3 mają więcej odmian niż ich odpowiedniki w M2. Ogólnie platformy interfejsu API M3 starają się być jak najbardziej podobne do swoich najbliższych odpowiedników w M2.

Ze względu na zaktualizowane systemy kolorów, typografii i kształtów komponenty M3 zwykle mapują się inaczej na nowe wartości motywów. Warto zajrzeć do katalogu tokenów w kodzie źródłowym Compose Material 3 jako źródła danych dotyczących mapowań.

Chociaż niektóre komponenty wymagają szczególnych uwagi, na początek możesz skorzystać z tych mapowań funkcji:

Brakujące interfejsy API:

M2 M3
androidx.compose.material.swipeable Jeszcze niedostępne

Zastąpione interfejsy API:

M2 M3
androidx.compose.material.BackdropScaffold Brak odpowiednika M3. Przejdź na Scaffold lub BottomSheetScaffold
androidx.compose.material.BottomDrawer Brak odpowiednika M3 – zamiast tego przejdź na ModalBottomSheet

Interfejsy API ze zmienionymi nazwami:

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 lub androidx.compose.material3.SuggestionChip
androidx.compose.material.ModalBottomSheetLayout androidx.compose.material3.ModalBottomSheet
androidx.compose.material.ModalDrawer androidx.compose.material3.ModalNavigationDrawer

Wszystkie pozostałe interfejsy 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

Najnowsze komponenty i układy M3 znajdziesz w omówieniu referencyjnym interfejsu Compose Material 3 API. Zaglądaj też na stronę wersji, na której znajdziesz nowe i zaktualizowane interfejsy API.

Scaffold, paski powiadomień i szuflada nawigacji

Porównanie rusztowania M2 i M3 z paskiem powiadomień i szufladą nawigacji
Rysunek 5. Rusztowanie M2 z paskiem powiadomień i szufladą nawigacji (po lewej) oraz rusztowanie M3 z paskiem powiadomień i szufladą nawigacji (po prawej).

Scaffold w M3 różni się od M2. Zarówno w M2, jak i M3 główny układ kompozycyjny ma nazwę Scaffold, ale pakiety importu i parametry są inne:

M2

import androidx.compose.material.Scaffold

Scaffold(
    // M2 scaffold parameters
)

M3

import androidx.compose.material3.Scaffold

Scaffold(
    // M3 scaffold parameters
)

Element M2 Scaffold zawiera teraz parametr backgroundColor o nazwie containerColor w Scaffold M3:

M2

import androidx.compose.material.Scaffold

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

M3

import androidx.compose.material3.Scaffold

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

Klasa M2 ScaffoldState nie istnieje już w M3, ponieważ zawiera parametr drawerState, który nie jest już potrzebny. Aby wyświetlać paski powiadomień za pomocą funkcji Scaffold w wersji M3, użyj zamiast niej narzędzia 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(…)
        }
    }
)

Wszystkie parametry drawer* z Scaffold M2 zostały usunięte z Scaffold M3. Obejmują one takie parametry jak drawerShape i drawerContent. Aby wyświetlić panel z interfejsem Scaffold M3, użyj funkcji kompozycyjnej panelu nawigacji, np. 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()
                }
            }
        )
    }
)

Górny pasek aplikacji

Porównanie rusztowania M2 i M3 z górnym paskiem aplikacji i przewijaną listą
Rysunek 6. Rusztowanie M2 z górnym paskiem aplikacji i przewijaną listą (w lewo) a rusztowanie M3 z górnym paskiem aplikacji i przewijaną listą (po prawej)

Najlepsze paski aplikacji w M3 są inne niż w M2. W obu wersjach główny element kompozycyjny głównego paska aplikacji nazywa się TopAppBar, ale pakiety importu i parametry różnią się:

M2

import androidx.compose.material.TopAppBar

TopAppBar(…)

M3

import androidx.compose.material3.TopAppBar

TopAppBar(…)

Jeśli treści były wcześniej centrowane w obiekcie TopAppBar M2, rozważ użycie narzędzia M3 CenterAlignedTopAppBar. Warto też znać MediumTopAppBar i LargeTopAppBar.

Górne paski aplikacji M3 zawierają nowy parametr scrollBehavior, który zapewnia różne funkcje podczas przewijania klasy TopAppBarScrollBehavior, np. zmianę wysokości. Działa to w połączeniu z przewijanymi treściami za pomocą parametru Modifer.nestedScroll. W TopAppBar M2 było to możliwe dzięki ręcznej zmianie parametru 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 { … }
    }
)

Dolny pasek nawigacyjny / pasek nawigacyjny

Porównanie dolnego paska nawigacyjnego M2 i paska nawigacyjnego M3
Rysunek 7. Dolny pasek nawigacyjny M2 (po lewej) i pasek nawigacyjny M3 (po prawej).

Dolna nawigacja w M2 została zmieniona w M3 na pasek nawigacyjny. W M2 dostępne są funkcje kompozycyjne BottomNavigation i BottomNavigationItem, a w M3 – NavigationBar i 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(…)
}

Przyciski, przyciski ikon i przyciski typu FAB

Porównanie przycisków M2 i M3
Rysunek 8. Przyciski M2 (lewy) i przyciski M3 (w prawo)

Przyciski, przyciski ikon i pływające przyciski poleceń (FAB) w M3 różnią się od tych w M2. M3 zawiera wszystkie elementy kompozycyjne przycisku 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 zawiera również nowe odmiany przycisków. Znajdziesz je w omówieniu plików referencyjnych interfejsu Compose Material 3.

Przełącz

Porównanie przełączników M2 i M3
Rysunek 9. Przełącznik M2 (lewy) i M3 (prawo).

Przełącznik w M3 różni się od M2. Zarówno w wersji M2, jak i M3 funkcja kompozycyjnej przełącznika nazywa się Switch, ale pakiety do importowania różnią się:

M2

import androidx.compose.material.Switch

Switch(…)

M3

import androidx.compose.material3.Switch

Switch(…)

Powierzchnie i wysokość

Porównanie wysokości względnej powierzchni M2 i M3 w motywach jasnych i ciemnych
Rysunek 10 Wysokość na powierzchni M2 w porównaniu z wysokością powierzchni M3 w motywie jasnym (po lewej) i ciemnym (po prawej).

Systemy powierzchni i wysokości w M3 są inne niż w M2. W M3 są 2 rodzaje wysokości:

  • Wysokość cienia (rzuca cień, tak jak w M2)
  • Wzniesienie zabarwienia (nakłada się na kolor, w nowej wersji M3)

W narzędziu Compose odnosi się to do funkcji M2 Surface i M3 Surface:

M2

import androidx.compose.material.Surface

Surface(
    elevation = …
) { … }

M3

import androidx.compose.material3.Surface

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

W M2 możesz użyć wartości elevation Dp w M2 zarówno dla shadowElevation, jak i tonalElevation w M3, w zależności od preferencji UX/UI. Surface to kompozycyjna kopia zapasowa większości komponentów, więc kompozycje komponentów mogą też ujawniać parametry wysokości, które musisz przenieść w ten sam sposób.

Ustawienie tonacji w M3 zastępuje koncepcję nakładek wysokości w ciemnych motywach M2 . W związku z tym funkcje ElevationOverlay i LocalElevationOverlay nie istnieją w wersji M3, a LocalAbsoluteElevation w M2 zostało zmienione na LocalAbsoluteTonalElevation w M3.

Wyróżnienie i treść alfa

Porównanie ikon M2 i M3 z wyróżnieniem tekstu
Rysunek 11 Wyróżnienie tekstu i ikony M2 (po lewej) oraz ikona M3 i wyróżnienie tekstu (po prawej)

Nacisk na M3 znacznie różni się od punktu M2. W M2 kładzie nacisk na używanie kolorów o określonych wartościach alfa, aby rozróżnić treści, np. tekst czy ikony. W wersji M3 dostępne są teraz różne podejścia:

  • Użycie kolorów z włączonym ustawieniem obok ich „wariantów” z rozszerzonego systemu kolorów M3.
  • używanie różnych grubości czcionki w tekście.

W związku z tym ContentAlpha i LocalContentAlpha nie istnieją w M3 i trzeba je zastąpić.

Na początek zalecane są te mapowania:

M2 M3
onSurface z: ContentAlpha.high Ogólnie: onSurface, FontWeight.MediumFontWeight.Black w przypadku tekstu
onSurface z: ContentAlpha.medium Ogólnie: onSurfaceVariant, FontWeight.ThinFontWeight.Normal w przypadku tekstu
onSurface z: ContentAlpha.disabled onSurface.copy(alpha = 0.38f)

Oto przykład naciskania ikon w wersjach M2 i 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(…)
}

Oto przykład uwydatnienia tekstu w wersjach M2 i 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
    )
}

Tła i kontenery

Tła w M2 są nazywane „kontenerami” w M3. Ogólnie w M3 możesz zastępować parametry background* w narzędziu M2 parametrami container*, korzystając z tych samych wartości. Na przykład:

M2

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

M3

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

Interoperacyjność widoków

Jeśli Twoja aplikacja zawiera widoki danych lub interoperacyjność XML i korzysta z biblioteki adaptera motywu MDC-Android Compose, musisz użyć wersji M3:

M2

implementation "com.google.android.material:compose-theme-adapter:$compose-theme-adapter-version"

M3

implementation "com.google.android.material:compose-theme-adapter-3:$compose-theme-adapter-3-version"

Najnowsze wersje znajdziesz na stronie wersji MDC-Android Compose Adapter.

Główną różnicą między wersjami M2 i M3 są odpowiednie kompozycje MdcTheme i Mdc3Theme:

M2

import com.google.android.material.composethemeadapter.MdcTheme

MdcTheme {
    // M2 content
}

M3

import com.google.android.material.composethemeadapter3.Mdc3Theme

Mdc3Theme {
    // M3 content
}

Więcej informacji znajdziesz w README.

Więcej informacji o migracji z Material 2 do Material 3 w widokach znajdziesz w przewodniku po migracji do Material Design 3.

Aby dowiedzieć się więcej o migracji z M2 do M3 w Compose, zapoznaj się z tymi dodatkowymi zasobami.

Dokumenty

Przykładowe aplikacje

Filmy

Dokumentacja API i kod źródłowy