Cómo migrar de Material 2 a Material 3 en Compose

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 impedimentos. 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:

  1. Agrega la dependencia de M3 junto con la dependencia de M2.
  2. Agrega versiones de M3 de los temas de tu app junto con las versiones de M2 de los temas de tu app.
  3. 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).
  4. Una vez que se haya migrado por completo, quita las versiones de M2 de los temas de tu app.
  5. 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
Clase de tamaño de ventana de Compose Material 3 androidx.compose.material3:material3-window-size-class:$m3-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

Comparación entre los sistemas de color de M2 y M3
Figura 1: Sistema de colores de M2 (izquierda) en comparación con el sistema de colores de M3 (derecha).

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 Neutra
Colores de M2 utilizados en Material Theme Builder para generar un esquema de colores de M3
Figura 2: Colores de M2 de Jetchat que se usan en Material Theme Builder para generar un esquema de colores de M3.

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

Comparación entre los sistemas de tipografía de M2 y M3
Figura 3: Sistema de tipografía M3 (izquierda) en comparación con el sistema de tipografía M2 (derecha)

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

Comparación entre los sistemas de formas de M2 y M3
Figura 4: El sistema de forma de M2 (izquierda) en comparación con el sistema de forma de M3 (derecha).

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 distinta, 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 en su lugar
androidx.compose.material.BottomDrawer Sin equivalente en M3; migra a ModalBottomSheet en su lugar

APIs con nombres diferentes:

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

Todas las demás APIs:

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

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

Comparación entre el andamiaje con la barra de notificaciones y el panel lateral de navegación de M2 y M3
Figura 5: Armazón de M2 con barra de notificaciones y panel lateral de navegación (izquierda) en comparación con el andamiaje con barra de notificaciones y panel lateral de navegación (derecha).

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, en su lugar:

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

Comparación entre el andamiaje con una barra superior de la app y una lista desplazada de M2 y M3
Figura 6: Armazón de M2 con barra superior de la app y lista desplazada (izquierda) en comparación con el andamiaje con barra superior de la app y lista desplazada (derecha)

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

Comparación entre la navegación inferior de M2 y la barra de navegación de M3
Figura 7: Navegación inferior de M2 (izquierda) en comparación con la barra de navegación de M3 (derecha).

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

Comparación entre los botones de M2 y M3
Figura 8: Botones de M2 (izquierda) frente a botones de M3 (derecha)

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.

Interruptor

Comparación entre los interruptores de M2 y M3
Figura 9: interruptor de M2 (izquierda) en comparación con el interruptor de M3 (derecha).

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

Comparación entre la elevación de superficie de M2 y la elevación de superficie de M3 en temas claros y oscuros
Figura 10: Comparación entre la elevación de superficie de M2 y la elevación de superficie de M3 en el tema claro (izquierda) y el tema oscuro (derecha).

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

Comparación entre el ícono y el énfasis de texto de M2 y M3
Figura 11: Ícono y énfasis de texto de M2 (izquierda) en comparación con el ícono y énfasis de texto de M3 (derecha)

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" desde el sistema de colores expandido de M3
  • 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(…)
}

Este es un ejemplo de énfasis de texto 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) {
    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
) { … }

Interoperabilidad de vistas

Si tu app incluye vistas o interoperabilidad de XML y usa la biblioteca de MDC-Android Compose Theme Adapter, debes usar la versión 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"

Consulta las versiones más recientes en la página de versiones de MDC-Android Compose Theme Adapter.

La diferencia principal entre las versiones M2 y M3 es el respectivo elemento MdcTheme y Mdc3Theme que admiten composición:

M2

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

MdcTheme {
    // M2 content
}

M3

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

Mdc3Theme {
    // M3 content
}

Consulta el archivo README para obtener más información.

Consulta la guía de migración a Material Design 3 a fin de obtener más información para migrar de Material 2 a Material 3 en vistas.

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

Videos

Referencia de la API y código fuente