Material Design 3 es la siguiente evolución de Material Design. Incluye temas y componentes actualizados, y funciones de personalización de Material You, como el color dinámico. Es una actualización de Material Design 2 y es coherente con el nuevo estilo visual y la IU del sistema de Android 12 y versiones posteriores.
Esta guía se centra en la migración desde la biblioteca de Compose Material Jetpack (androidx.compose.material) hasta la biblioteca de Compose Material 3 Jetpack (androidx.compose.material3).
Enfoques
En general, no deberías usar M2 ni M3 en una sola app a largo plazo. Esto se debe a que los dos sistemas de diseño y las bibliotecas respectivas difieren, de manera significativa, en términos de sus diseños de UX/IU e implementaciones de Compose.
Es posible que tu app pueda usar un sistema de diseño, por ejemplo, uno creado con Figma. En esos casos, también te recomendamos que tú o tu equipo de diseño migren de M2 a M3 antes de comenzar la migración de Compose. No tiene sentido migrar una app a M3 si su diseño de UX/IU se basa en M2.
Además, tu enfoque de migración debe diferir según el tamaño, la complejidad y el diseño de la UX/IU de tu app. Esto te ayuda a minimizar el impacto en tu base de código. Debes adoptar un enfoque por etapas para la migración.
Cuándo migrar
Debes comenzar la migración lo antes posible. Sin embargo, es importante considerar si tu app se encuentra en una posición realista para migrar por completo de M2 a M3. Existen algunos impedimentos que debes considerar antes de comenzar:
Situación | Enfoque recomendado |
---|---|
Sin bloqueadores | Comienza la migración por etapas |
Un componente de M2 aún no está disponible en M3. Consulta la siguiente sección Componentes y diseños. | Comienza la migración por etapas |
Tú o tu equipo de diseño no migraron el sistema de diseño de la app de M2 a M3. | Migra el sistema de diseño de M2 a M3 y, luego, inicia la migración por etapas. |
Incluso si te encuentras en las situaciones anteriores, debes adoptar un enfoque por etapas para la migración antes de confirmar y lanzar una actualización de la app. En estos casos, usarías M2 y M3 en paralelo, y dejarías de usar M2 de forma gradual mientras migras a M3.
Enfoque por etapas
Los pasos generales para una migración por etapas son los siguientes:
- Agrega la dependencia de M3 junto con la dependencia de M2.
- Agrega versiones de M3 de los temas de tu app junto con las versiones de M2 de los temas de tu app.
- Migra a M3 módulos individuales, pantallas o elementos que admiten composición, según el tamaño y la complejidad de tu app (consulta las siguientes secciones para obtener más detalles).
- Una vez que se haya migrado por completo, quita las versiones de M2 de los temas de tu app.
- Quita la dependencia de M2.
Dependencias
M3 tiene un paquete y una versión diferentes a M2:
M2
implementation "androidx.compose.material:material:$m2-version"
M3
implementation "androidx.compose.material3:material3:$m3-version"
Consulta las versiones más recientes de M3 en la página de versiones de Compose Material 3.
No se modificaron otras dependencias de Material fuera de las bibliotecas principales de M2 y M3. Usan una combinación de paquetes y versiones de M2 y M3, pero no afecta la migración. Pueden usarse tal como están con M3:
Biblioteca | Paquete y versión |
---|---|
Íconos de Compose Material | androidx.compose.material:material-icons-*:$m2-version |
Ondas de Compose Material | androidx.compose.material:material-ripple:$m2-version |
APIs experimentales
Algunas APIs de M3 se consideran experimentales. En esos casos, debes habilitar en el nivel de la función o del archivo con la anotación ExperimentalMaterial3Api
:
import androidx.compose.material3.ExperimentalMaterial3Api
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppComposable() {
// M3 composables
}
Temas
En M2 y M3, el tema que admite composición se denomina MaterialTheme
, pero los paquetes de importación y los parámetros difieren:
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
}
Color
El sistema de colores de M3 es significativamente diferente al de M2. La cantidad de parámetros de color aumentó, tienen nombres diferentes y se asignan de forma distinta a los componentes de M3. En Compose, esto se aplica a la clase Colors
de M2, la clase ColorScheme
de M3 y las funciones relacionadas:
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
}
Dadas las diferencias significativas entre los sistemas de color de M2 y M3, no existe una asignación razonable para los parámetros Color
. En su lugar, usa la herramienta Material Theme Builder para generar un esquema de colores de M3. Utiliza los colores de M2 como colores de origen principales en la herramienta, que la herramienta expande a paletas tonales que utiliza el esquema de colores de M3. Se recomiendan las siguientes asignaciones como punto de partida:
M2 | Material Theme Builder |
---|---|
primary |
Principal |
primaryVariant |
Secondary |
secondary |
Terciario |
surface o background |
Neutro |
Puedes copiar los valores de código hexadecimales de color para los temas claro y oscuro desde la herramienta y usarlos a fin de implementar una instancia de ColorScheme de M3. Como alternativa, Material Theme Builder puede exportar código de Compose.
isLight
A diferencia de la clase Colors
de M2, la clase ColorScheme
de M3 no incluye un parámetro isLight
. En general, debes intentar modelar lo que necesite esta información a nivel del tema. Por ejemplo:
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
…
}
}
Para obtener más información, consulta la guía de sistemas de diseño personalizado en Compose.
Color dinámico
Una nueva función de M3 es el color dinámico. En lugar de usar colores personalizados, un ColorScheme
de M3 puede usar colores de fondo de pantalla de dispositivo en Android 12 y versiones posteriores, mediante las siguientes funciones:
Tipografía
El sistema de tipografía en M3 es diferente al de M2. La cantidad de parámetros de tipografía es casi la misma, pero tienen nombres diferentes y se asignan de forma distinta a los componentes de M3. En Compose, esto se aplica a la clase Typography
de M2 y la clase Typography
de 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
)
Se recomiendan las siguientes asignaciones de parámetro TextStyle
como punto de partida:
M2 | M3 |
---|---|
h1 |
displayLarge |
h2 |
displayMedium |
h3 |
displaySmall |
N/A | headlineLarge |
h4 |
headlineMedium |
h5 |
headlineSmall |
h6 |
titleLarge |
subtitle1 |
titleMedium |
subtitle2 |
titleSmall |
body1 |
bodyLarge |
body2 |
bodyMedium |
caption |
bodySmall |
button |
labelLarge |
N/A | labelMedium |
overline |
labelSmall |
Forma
El sistema de forma en M3 es diferente al de M2. La cantidad de parámetros de forma aumentó, tienen nombres diferentes y se asignan de forma diferente a los componentes de M3. En Compose, esto se aplica a la clase Shapes
de M2 y la clase Shapes
de 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
)
Se recomiendan las siguientes asignaciones de parámetro Shape
como punto de partida:
M2 | M3 |
---|---|
N/A | extraSmall |
small |
small |
medium |
medium |
large |
large |
N/A | extraLarge |
Componentes y diseños
La mayoría de los componentes y diseños de M2 están disponibles en M3. Sin embargo, faltan algunos y se agregaron otros que no existían en M2. Además, algunos componentes de M3 tienen más variaciones que sus equivalentes en M2. En general, las plataformas de la API de M3 intentan ser lo más similares posible a sus equivalentes más parecidos en M2.
Dados los actualizados sistemas de color, tipografía y forma, los componentes de M3 suelen asignarse, de manera diferente, a los nuevos valores de temas. Se recomienda consultar el directorio de tokens en el código fuente de Compose Material 3 como fuente confiable para estas asignaciones.
Si bien algunos componentes requieren consideraciones especiales, se recomiendan las siguientes asignaciones de funciones como punto de partida:
APIs faltantes:
M2 | M3 |
---|---|
androidx.compose.material.swipeable |
Aún no disponible |
APIs reemplazadas:
M2 | M3 |
---|---|
androidx.compose.material.BackdropScaffold |
Sin equivalente en M3; migra a Scaffold o BottomSheetScaffold |
androidx.compose.material.BottomDrawer |
No hay equivalente de M3; en su lugar, migra a ModalBottomSheet |
APIs con nombres diferentes:
Todas las demás APIs:
Consulta los componentes y diseños más recientes de M3 en la descripción general de referencia de la API de Compose Material 3 y consulta la página de versiones para conocer las APIs nuevas y actualizadas.
Andamiaje, barra de notificaciones y panel lateral de navegación
El andamiaje en M3 es diferente al de M2. En M2 y M3, el diseño principal que admite composición se denomina Scaffold
, pero los paquetes de importación y los parámetros difieren:
M2
import androidx.compose.material.Scaffold
Scaffold(
// M2 scaffold parameters
)
M3
import androidx.compose.material3.Scaffold
Scaffold(
// M3 scaffold parameters
)
Scaffold
de M2 contiene un parámetro backgroundColor
que ahora se denomina containerColor
en Scaffold
de M3:
M2
import androidx.compose.material.Scaffold
Scaffold(
backgroundColor = …,
content = { … }
)
M3
import androidx.compose.material3.Scaffold
Scaffold(
containerColor = …,
content = { … }
)
La clase ScaffoldState
de M2 ya no existe en M3 porque contiene un parámetro drawerState
que ya no es necesario. Para mostrar las barras de notificaciones con Scaffold
de M3, usa SnackbarHostState
en su lugar:
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(…)
}
}
)
Todos los parámetros drawer*
de Scaffold
de M2 se quitaron de Scaffold
de M3. Estos incluyen parámetros, como drawerShape
y drawerContent
. Para mostrar un panel lateral con Scaffold
de M3, usa un panel lateral de navegación que admita composición, como 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 superior de la app
Las barras superiores de la app en M3 son diferentes de las de M2. En M2 y M3, la barra superior de la app que admite composición se denomina TopAppBar
, pero los paquetes de importación y los parámetros difieren:
M2
import androidx.compose.material.TopAppBar
TopAppBar(…)
M3
import androidx.compose.material3.TopAppBar
TopAppBar(…)
Considera usar CenterAlignedTopAppBar
de M3 si antes enfocabas el contenido dentro de TopAppBar
de M2. También se recomienda tener en cuenta MediumTopAppBar
y LargeTopAppBar
.
Las barras superiores de la app de M3 contienen un nuevo parámetro scrollBehavior
para proporcionar diferentes funcionalidades cuando te desplazas por la clase TopAppBarScrollBehavior
, por ejemplo, cuando se cambia la elevación. Funciona junto con el contenido de desplazamiento mediante Modifer.nestedScroll
. Era posible en TopAppBar
de M2 cuando se cambiaba el parámetro elevation
de forma manual:
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 { … }
}
)
Navegación inferior y barra de navegación
Se cambió el nombre de la navegación inferior en M2 a barra de navegación en M3. En M2, se incluyen los elementos BottomNavigation
y BottomNavigationItem
que admiten composición, mientras que, en M3, se incluyen los elementos NavigationBar
y NavigationBarItem
que admiten composición:
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(…)
}
Botones, botones de íconos y BAF
Los botones, botones de íconos y botones de acción flotante (BAF) en M3 son diferentes de los de M2. M3 incluye todos los elementos de botones de M2 que admiten composición:
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 también incluye nuevas variaciones de botones. Consulta la descripción general de la referencia de la API de Compose Material 3.
Cambiar
El interruptor en M3 es diferente al de M2. En M2 y M3, el interruptor que admite composición se denomina Switch
, pero los paquetes de importación difieren:
M2
import androidx.compose.material.Switch
Switch(…)
M3
import androidx.compose.material3.Switch
Switch(…)
Superficies y elevación
Los sistemas de superficie y elevación en M3 son diferentes a los de M2. Existen dos tipos de elevación en M3:
- Elevación de sombras (proyecta una sombra, igual que M2)
- Elevación tonal (superpone un color, nueva característica en M3)
En Compose, se aplica a las funciones Surface
de M2 y Surface
de M3:
M2
import androidx.compose.material.Surface
Surface(
elevation = …
) { … }
M3
import androidx.compose.material3.Surface
Surface(
shadowElevation = …,
tonalElevation = …
) { … }
Puedes usar los valores elevation
Dp
en M2 para shadowElevation
o tonalElevation
en M3, según las preferencias de diseño de UX/IU.
Surface
es el elemento de copia de seguridad que admite composición detrás de la mayoría de los componentes, por lo que es posible que estos también expongan parámetros de elevación que debes migrar de la misma manera.
La elevación tonal en M3 reemplaza el concepto de superposiciones de elevación en los temas oscuros de M2. Como resultado, ElevationOverlay
y LocalElevationOverlay
no existen en M3, y LocalAbsoluteElevation
en M2 cambió a LocalAbsoluteTonalElevation
en M3.
Énfasis y versión alfa de contenido
El énfasis en M3 es significativamente diferente al de M2. En M2, el énfasis implicaba usar colores activados con ciertos valores alfa para diferenciar el contenido, como el texto y los íconos. En M3, ahora se aplica un par de enfoques diferentes:
- Usar los colores activados junto con los colores de variante activada del sistema de colores expandido de M3
- Puedes usar diferentes tamaños de fuente para el texto.
Como resultado, ContentAlpha
y LocalContentAlpha
ya no existen en M3 y deben reemplazarse.
Se recomiendan las siguientes asignaciones como punto de partida:
M2 | M3 |
---|---|
onSurface con ContentAlpha.high |
onSurface en general, FontWeight.Medium - FontWeight.Black para texto |
onSurface con ContentAlpha.medium |
onSurfaceVariant en general, FontWeight.Thin - FontWeight.Normal para texto |
onSurface con ContentAlpha.disabled |
onSurface.copy(alpha = 0.38f) |
Este es un ejemplo de énfasis de íconos en M2 en comparación con 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(…)
}
Estos son ejemplos de énfasis de texto en M2 y 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
)
}
Fondos y contenedores
Los fondos en M2 se denominan contenedores en M3. En general, puedes reemplazar los parámetros background*
en M2 por container*
en M3, mediante los mismos valores.
Por ejemplo:
M2
Badge(
backgroundColor = MaterialTheme.colors.primary
) { … }
M3
Badge(
containerColor = MaterialTheme.colorScheme.primary
) { … }
Vínculos útiles
Para obtener más información sobre la migración de M2 a M3 en Compose, consulta los siguientes recursos adicionales.
Documentos
Apps de ejemplo
- Reply, app de ejemplo de M3
- Jetchat, app de app de ejemplo de migración de M2 a M3
- Jetnews, app de app de ejemplo de migración de M2 a M3
- Ahora en el módulo :core-designsystem de la app de gran impacto de M3 para Android
Videos
Referencia de la API y código fuente
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Material Design 2 en Compose
- Material Design 3 en Compose
- Sistemas de diseño personalizado en Compose