Material Design 3 è la nuova evoluzione di Material Design. Include componenti, temi e funzionalità di personalizzazione Material You aggiornati, come il colore dinamico. È un aggiornamento di Material Design 2 ed è coerente con il nuovo stile visivo e l'UI di sistema di Android 12 e versioni successive.
Questa guida si concentra sulla migrazione dalla libreria Jetpack Compose Material (androidx.compose.material) alla libreria Jetpack Compose Material 3 (androidx.compose.material3).
Approcci
In generale, non utilizzare sia M2 che M3 in una singola app a lungo termine. Questo perché i due sistemi di progettazione e le rispettive librerie differiscono in modo significativo in termini di progettazione UX/UI e implementazioni di Compose.
La tua app potrebbe utilizzare un sistema di progettazione, ad esempio uno creato utilizzando Figma. In questi casi, ti consigliamo vivamente anche di eseguire la migrazione da M2 a M3 prima di iniziare la migrazione di Compose. Non ha senso eseguire la migrazione di un'app a M3 se il suo design UX/UI è basato su M2.
Inoltre, il tuo approccio alla migrazione deve tenere conto delle dimensioni, della complessità e del design UX/UI della tua app. In questo modo, puoi ridurre al minimo l'impatto sul codebase. Adotta un approccio graduale alla migrazione.
Quando eseguire la migrazione
Idealmente, dovresti iniziare la migrazione il prima possibile. Tuttavia, è importante valutare se la tua app si trova in una posizione realistica per eseguire la migrazione completa da M2 a M3. Prima di iniziare, devi prendere in considerazione alcuni scenari di blocco da esaminare:
| Scenario | Approccio consigliato |
|---|---|
| La tua app non presenta blocchi significativi. | Inizia la migrazione in più fasi. |
| La tua app utilizza un componente di M2 non ancora disponibile in M3. Consulta la sezione Componenti e layout. | Inizia la migrazione in più fasi. |
| Tu o il tuo team di progettazione non avete eseguito la migrazione del sistema di progettazione dell'app da M2 a M3. | Esegui la migrazione del sistema di progettazione da M2 a M3, quindi inizia la migrazione in più fasi. |
Anche se sei interessato dagli scenari precedenti, devi adottare un approccio graduale alla migrazione prima di eseguire il commit e rilasciare un aggiornamento dell'app. In questi casi, utilizzerai M2 e M3 affiancati e ritirerai gradualmente M2 durante la migrazione a M3.
Approccio graduale
I passaggi generali per una migrazione graduale sono i seguenti:
- Aggiungi la dipendenza M3 insieme a quella M2.
- Aggiungi le versioni M3 dei temi della tua app insieme alle versioni M2 dei temi della tua app.
- Esegui la migrazione di singoli moduli, schermate o composable a M3, a seconda delle dimensioni e della complessità dell'app (per i dettagli, consulta le sezioni seguenti).
- Una volta completata la migrazione, rimuovi le versioni M2 dei temi della tua app.
- Rimuovi la dipendenza M2.
Dipendenze
M3 ha un pacchetto e una versione diversi rispetto a M2:
M2
implementation "androidx.compose.material:material:$m2-version"
M3
implementation "androidx.compose.material3:material3:$m3-version"
Consulta le versioni più recenti di M3 nella pagina delle release di Compose Material 3.
Le altre dipendenze di Material al di fuori delle librerie M2 e M3 principali non sono cambiate. Utilizzano una combinazione di pacchetti e versioni M2 e M3, ma ciò non ha alcun impatto sulla migrazione. Possono essere utilizzati così come sono con M3:
| Raccolta | Pacchetto e versione |
|---|---|
| Comporre icone Material | androidx.compose.material:material-icons-*:$m2-version |
| Compose Material Ripple | androidx.compose.material:material-ripple:$m2-version |
API sperimentali
Alcune API M3 sono considerate sperimentali. In questi casi, devi attivare
l'opzione a livello di funzione o file utilizzando l'annotazione
ExperimentalMaterial3Api:
import androidx.compose.material3.ExperimentalMaterial3Api
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppComposable() {
// M3 composables
}
Applicazione tema
Sia in M2 che in M3, il componibile del tema si chiama MaterialTheme, ma i pacchetti di importazione e i parametri sono diversi:
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
}
Colore
Il sistema di colori in M3 è notevolmente diverso rispetto a M2. Il numero di parametri di colore è aumentato, hanno nomi diversi e vengono mappati ai componenti di M3 in modo differente. In Compose, questo vale per la classe Colors di M2, la classe ColorScheme di M3 e le funzioni correlate:
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
}
Date le differenze significative tra i sistemi di colori M2 e M3, non esiste
un mapping ragionevole per i parametri Color. Utilizza invece lo strumento
Material Theme Builder per generare una combinazione di colori M3. Utilizza i colori M2
come colori di origine principali nello strumento, che lo strumento espande in tavolozze tonali
utilizzate dalla combinazione di colori M3. Ti consigliamo le seguenti mappature
come punto di partenza:
| M2 | Generatore di temi Material |
|---|---|
primary |
Principale |
primaryVariant |
Secondario |
secondary |
Terziario |
surface o background |
Né soddisfatto né insoddisfatto |
Puoi copiare i valori del codice esadecimale del colore per i temi chiaro e scuro dallo strumento e utilizzarli per implementare un'istanza di M3 ColorScheme. In alternativa, Material Theme Builder può esportare il codice Compose.
isLight
A differenza della classe Colors di M2, la classe ColorScheme di M3 non include un parametro
isLight. In generale, dovresti provare a modellare tutto ciò che richiede
queste informazioni a livello di tema. Ad esempio:
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
…
}
}
Per saperne di più, consulta la Guida ai sistemi di progettazione personalizzati in Compose.
Colore dinamico
Una nuova funzionalità di M3 è il colore dinamico. Anziché utilizzare colori personalizzati, un M3 ColorScheme può utilizzare i colori dello sfondo del dispositivo su Android 12 e versioni successive, utilizzando le seguenti funzioni:
Tipografia
Il sistema tipografico in M3 è diverso rispetto a M2. Il numero di parametri tipografici è più o meno lo stesso, ma hanno nomi diversi e vengono mappati ai componenti di M3 in modo differente. In Compose, questo vale per la classe Typography di M2 e per la classe Typography di M3:
M2
import androidx.compose.material.Typography
val AppTypography = Typography(
// M2 TextStyle parameters
)
M3
import androidx.compose.material3.Typography
val AppTypography = Typography(
// M3 TextStyle parameters
)
Come punto di partenza, ti consigliamo le seguenti mappature dei parametri TextStyle:
| M2 | M3 |
|---|---|
h1 |
displayLarge |
h2 |
displayMedium |
h3 |
displaySmall |
| N/D | headlineLarge |
h4 |
headlineMedium |
h5 |
headlineSmall |
h6 |
titleLarge |
subtitle1 |
titleMedium |
subtitle2 |
titleSmall |
body1 |
bodyLarge |
body2 |
bodyMedium |
caption |
bodySmall |
button |
labelLarge |
| N/D | labelMedium |
overline |
labelSmall |
Forma
Il sistema di forme in M3 è diverso rispetto a M2. Il numero di parametri
di forma è aumentato, hanno un nome diverso e vengono mappati
ai componenti di M3 in modo differente. In Compose, questo vale per la classe Shapes di M2 e per la classe
Shapes di M3:
M2
import androidx.compose.material.Shapes
val AppShapes = Shapes(
// M2 Shape parameters
)
M3
import androidx.compose.material3.Shapes
val AppShapes = Shapes(
// M3 Shape parameters
)
Come punto di partenza, ti consigliamo le seguenti mappature dei parametri Shape:
| M2 | M3 |
|---|---|
| N/D | extraSmall |
small |
small |
medium |
medium |
large |
large |
| N/D | extraLarge |
Componenti e layout
La maggior parte dei componenti e dei layout di M2 è disponibile in M3. Tuttavia, alcuni non sono presenti, mentre altri sono nuovi e non esistevano in M2. Inoltre, alcuni componenti di M3 hanno più varianti rispetto ai loro equivalenti in M2. In generale, le superfici API M3 sono progettate per essere il più simili possibile ai loro equivalenti più vicini in M2.
Dato l'aggiornamento dei sistemi di colori, tipografia e forme, i componenti M3 tendono a essere mappati in modo diverso rispetto ai nuovi valori dei temi. Ti consigliamo di consultare la directory dei token nel codice sorgente di Compose Material 3 come fonte di verità per questi mapping.
Sebbene alcuni componenti richiedano considerazioni speciali, le seguenti mappature delle funzioni sono consigliate come punto di partenza:
API mancanti:
| M2 | M3 |
|---|---|
androidx.compose.material.swipeable |
Non ancora disponibile |
API sostituite:
| M2 | M3 |
|---|---|
androidx.compose.material.BackdropScaffold |
Nessun equivalente in M3, esegui la migrazione a Scaffold o BottomSheetScaffold |
androidx.compose.material.BottomDrawer |
Nessun equivalente in M3, esegui la migrazione a ModalBottomSheet |
API rinominate:
Tutte le altre API:
Consulta i componenti e i layout M3 più recenti nella panoramica di riferimento dell'API Compose Material 3 e tieni d'occhio la pagina delle release per le API nuove e aggiornate.
Struttura, snackbar e riquadro di navigazione a scomparsa
Lo scaffold in M3 è diverso rispetto a M2. Sia in M2 che in M3, il componibile del layout principale
si chiama Scaffold, ma i pacchetti di importazione e i parametri sono diversi:
M2
import androidx.compose.material.Scaffold
Scaffold(
// M2 scaffold parameters
)
M3
import androidx.compose.material3.Scaffold
Scaffold(
// M3 scaffold parameters
)
Il parametro backgroundColor contenuto in Scaffold di M2 ora si chiama
containerColor in Scaffold di M3:
M2
import androidx.compose.material.Scaffold
Scaffold(
backgroundColor = …,
content = { … }
)
M3
import androidx.compose.material3.Scaffold
Scaffold(
containerColor = …,
content = { … }
)
La classe M2 ScaffoldState non esiste più in M3 perché contiene un parametro
drawerState che non è più necessario. Per mostrare le snackbar con
Scaffold M3, utilizza 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(…)
}
}
)
Tutti i parametri drawer* di M2 Scaffold sono stati rimossi da M3 Scaffold. Sono inclusi parametri come drawerShape e
drawerContent. Per mostrare un riquadro con Scaffold di M3, utilizza invece un
componente componibile per il riquadro di navigazione, ad esempio 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()
}
}
)
}
)
Barra dell'app in alto
Le barre dell'app in alto in M3 sono diverse da quelle in M2. Sia in M2 che in M3, il componibile principale della barra delle app superiore si chiama TopAppBar, ma i pacchetti di importazione e i parametri sono diversi:
M2
import androidx.compose.material.TopAppBar
TopAppBar(…)
M3
import androidx.compose.material3.TopAppBar
TopAppBar(…)
Prendi in considerazione l'utilizzo di M3 CenterAlignedTopAppBar se in precedenza
centravi i contenuti all'interno di M2 TopAppBar. È bene conoscere anche il
MediumTopAppBar e il LargeTopAppBar.
Le barre delle app M3 contengono un nuovo parametro scrollBehavior per fornire funzionalità diverse
durante lo scorrimento della classe TopAppBarScrollBehavior, ad esempio
la modifica dell'elevazione. Funziona in combinazione con lo scorrimento dei contenuti utilizzando
Modifier.nestedScroll. Ciò era possibile in M2 TopAppBar modificando
manualmente il parametro 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 { … }
}
)
Navigazione in basso e barra di navigazione
La navigazione in basso in M2 è stata rinominata barra di navigazione in
M3. In M2 sono presenti i componibili BottomNavigation e
BottomNavigationItem, mentre in M3 sono presenti i componibili
NavigationBar e 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(…)
}
Pulsanti, pulsanti con icone e FAB
Pulsanti, pulsanti con icone e Floating Action Button (FAB) in M3 sono diversi da quelli in M2. M3 include tutti i composable dei pulsanti 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 include anche nuove varianti di pulsanti. Dai un'occhiata alla panoramica del riferimento API di Compose Material 3.
Switch
L'interruttore in M3 è diverso rispetto a M2. Sia in M2 che in M3, il componibile
dell'interruttore si chiama Switch, ma i pacchetti di importazione sono diversi:
M2
import androidx.compose.material.Switch
Switch(…)
M3
import androidx.compose.material3.Switch
Switch(…)
Superfici ed elevazione
I sistemi di superficie ed elevazione in M3 sono diversi rispetto a M2. Esistono due tipi di elevazione in M3:
- Elevazione ombra (proietta un'ombra, come M2)
- Elevazione tonale (sovrappone un colore, novità di M3)
In Compose, questo vale per la funzione Surface di M2 e per la funzione
Surface di M3:
M2
import androidx.compose.material.Surface
Surface(
elevation = …
) { … }
M3
import androidx.compose.material3.Surface
Surface(
shadowElevation = …,
tonalElevation = …
) { … }
Puoi utilizzare i valori elevation Dp in M2 sia per shadowElevation
che per tonalElevation in M3, a seconda delle preferenze di progettazione UX/UI.
Surface è il composable di supporto della maggior parte dei componenti, pertanto i composable dei componenti potrebbero esporre anche parametri di elevazione che devi migrare nello stesso modo.
L'elevazione tonale in M3 sostituisce il concetto di overlay di elevazione nei temi scuri di M2. Di conseguenza, ElevationOverlay e LocalElevationOverlay
non esistono in M3 e LocalAbsoluteElevation in M2 è stato modificato in
LocalAbsoluteTonalElevation in M3.
Enfasi e alpha dei contenuti
L'enfasi in M3 è notevolmente diversa rispetto a M2. In Material 2, l'enfasi prevedeva l'utilizzo di colori on con determinati valori alfa per differenziare i contenuti come testo e icone. In M3, ora sono disponibili due approcci diversi:
- Utilizzo dei colori on insieme alle relative varianti on del sistema di colori M3 espanso.
- Utilizzo di spessori diversi per il testo.
Di conseguenza, ContentAlpha e LocalContentAlpha non esistono in
M3 e devono essere sostituiti.
Le seguenti mappature sono consigliate come punto di partenza:
| M2 | M3 |
|---|---|
onSurface con ContentAlpha.high |
onSurface in generale, FontWeight.Medium - FontWeight.Black per il testo |
onSurface con ContentAlpha.medium |
onSurfaceVariant in generale, FontWeight.Thin - FontWeight.Normal per il testo |
onSurface con ContentAlpha.disabled |
onSurface.copy(alpha = 0.38f) |
Ecco un esempio di enfasi delle icone in M2 rispetto a 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(…)
}
Ecco alcuni esempi di enfasi del testo in M2 e 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
)
}
Sfondi e contenitori
Gli sfondi in M2 sono chiamati contenitori in M3. In generale, puoi sostituire
i parametri background* in M2 con container* in M3, utilizzando gli stessi valori.
Ad esempio:
M2
Badge(
backgroundColor = MaterialTheme.colors.primary
) { … }
M3
Badge(
containerColor = MaterialTheme.colorScheme.primary
) { … }
Link utili
Per scoprire di più sulla migrazione da M2 a M3 in Compose, consulta le seguenti risorse aggiuntive.
Documenti
App di esempio
- App di esempio Reply M3
- Migrazione dall'app di esempio Jetchat da M2 a M3
- Migrazione dall'app di esempio Jetnews da M2 a M3
- Now in Android M3 hero app :core-designsystem module
Video
Riferimento API e codice sorgente
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Material Design 2 in Compose
- Material Design 3 in Compose
- Sistemi di progettazione personalizzati in Compose