O Material Design 3 (link em inglês) é a próxima evolução do Material Design. Ele inclui temas, componentes e recursos de personalização do Material You atualizados, como cores dinâmicas. É uma atualização do Material Design 2 e é coeso com o novo estilo visual e a interface do sistema no Android 12 e versões mais recentes.
Este guia se concentra na migração da biblioteca Jetpack do Compose Material (androidx.compose.material) para a biblioteca Jetpack do Compose Material 3 (androidx.compose.material3).
Abordagens
Em geral, não use M2 e M3 em um único app de longo prazo. Isso ocorre porque os dois sistemas de design e as respectivas bibliotecas diferem significativamente em termos de designs de UX/IU e implementações do Compose.
O app pode usar um sistema de design, como o criado pelo Figma. Nesses casos, também recomendamos que você ou sua equipe de design migre de M2 para M3 antes de iniciar a migração do Compose. Não faz sentido migrar um app para o M3 se o design da UX/UI se baseia no M2.
Além disso, a abordagem da migração varia de acordo com o tamanho, a complexidade e o design da UX/UI do app. Isso minimiza o impacto na sua base de código. Adote uma abordagem por etapas.
Quando migrar
Inicie a migração assim que possível. No entanto, é importante considerar se o app está em uma posição realista para migrar totalmente do M2 para o M3. Considere alguns cenários de bloqueio antes de começar:
Cenário | Abordagem recomendada |
---|---|
Sem bloqueadores | Iniciar a migração por etapas. |
Um componente do M2 ainda não está disponível no M3. Consulte a seção Componentes e layouts abaixo. | Iniciar a migração por etapas. |
Você ou sua equipe de design não migraram o sistema de design do app do M2 para o M3. | Migrar o sistema de design do M2 para o M3 e depois iniciar a migração por etapas. |
Mesmo que você seja afetado pelos cenários acima, é necessário adotar uma abordagem por etapas para a migração antes de confirmar e lançar uma atualização do app. Nesses casos, use o M2 e o M3 em conjunto e, gradualmente, desative o M2 enquanto migra para o M3.
Abordagem por etapas
As etapas gerais para uma migração são estas:
- Adicione a dependência M3 junto com a dependência M2.
- Adicione as versões M3 dos temas do app junto com as versões M2 dos temas do app.
- Migre módulos individuais, telas ou elementos de composição para o M3, dependendo do tamanho e da complexidade do app. Nas seções abaixo você encontra mais detalhes.
- Após a migração, remova as versões M2 dos temas do app.
- Remova a dependência do M2.
Dependências
O M3 tem um pacote e uma versão separados para o M2:
M2
implementation "androidx.compose.material:material:$m2-version"
M3
implementation "androidx.compose.material3:material3:$m3-version"
Consulte as versões mais recentes do M3 na página de versões do Compose Material 3.
Outras dependências do Material Design fora das bibliotecas principais M2 e M3 não foram modificadas. Elas usam uma combinação de pacotes e versões do M2 e do M3, mas isso não afeta a migração. Elas podem ser usadas no estado em que se encontram com o M3:
Biblioteca | Pacote e versão |
---|---|
Ícones do Compose Material | androidx.compose.material:material-icons-*:$m2-version |
Ondulações do Compose Material | androidx.compose.material:material-ripple:$m2-version |
APIs experimentais
Algumas APIs do M3 são consideradas experimentais. Nesses casos, vai ser necessário ativar
o nível da função ou do arquivo usando a anotação ExperimentalMaterial3Api
:
import androidx.compose.material3.ExperimentalMaterial3Api
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppComposable() {
// M3 composables
}
Temas
Nas versões M2 e M3, o tema de composição é chamado de MaterialTheme
, mas os pacotes
e parâmetros de importação são diferentes:
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
}
Cor
O sistema de cores (link em inglês) no M3 é significativamente diferente do M2. O
número de parâmetros de cor aumentou, eles têm nomes diferentes e são
mapeados de forma diferente dos componentes do M3. No Compose, isso se aplica à classe
Colors
do M2, à classe ColorScheme
do M3 e às funções 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
}
Devido às diferenças significativas entre os sistemas de cores M2 e M3, não há
mapeamento razoável para os parâmetros Color
. Em vez disso, use a ferramenta do criador de Temas do
Material Design para gerar um esquema de cores do M3. Use as cores M2
como cores de origem principais na ferramenta, que a ferramenta expande em paletas
tonais usadas pelo esquema de cores M3. Os mapeamentos abaixo são recomendados como
ponto de partida:
M2 | Criador de Temas do Material Design |
---|---|
primary |
Primary |
primaryVariant |
Secundário |
secondary |
Tertiary |
surface ou background |
Neutral |
É possível copiar os valores de código hexadecimal de cores para os temas claro e escuro da ferramenta e usá-los para implementar uma instância ColorScheme do M3. Como alternativa, o Criador de Temas do Material Design pode exportar o código do Compose.
isLight
Ao contrário da classe Colors
do M2, a classe ColorScheme
do M3 não inclui um
parâmetro isLight
. Em geral, você precisa tentar modelar os elementos que precisarem
dessas informações no nível do tema. Exemplo:
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
…
}
}
Consulte o guia de sistemas de design personalizados no Compose para mais informações.
Cores dinâmicas
Um novo recurso do M3 é a cor dinâmica (link em inglês). Em vez de usar cores
personalizadas, um ColorScheme
do M3 pode usar as cores do plano de fundo do dispositivo no Android
12 e versões mais recentes, usando estas funções:
Tipografia
O sistema de tipografia (link em inglês) do M3 é diferente do M2. O número de
parâmetros de tipografia é aproximadamente o mesmo, mas eles têm nomes diferentes e
são mapeados de maneira diferente dos componentes do M3. No Compose, isso se aplica às classes
Typography
do M2 e à classe Typography
do 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
)
Os mapeamentos de parâmetro TextStyle
abaixo são recomendados como ponto
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
O sistema de formas (link em inglês) no M3 é diferente do M2. O número de parâmetros
de forma aumentou, eles são nomeados de forma diferente e são mapeados de forma diferente dos
componentes do M3. No Compose, isso se aplica à classe Shapes
do M2 e à
classe Shapes
do 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
)
Os mapeamentos de parâmetro Shape
abaixo são recomendados como ponto
de partida:
M2 | M3 |
---|---|
N/A | extraSmall |
small |
small |
medium |
medium |
large |
large |
N/A | extraLarge |
Componentes e layouts
A maioria dos componentes e layouts do M2 está disponível no M3. No entanto, alguns estão ausentes e outros são novos e não existiam no M2. Além disso, alguns componentes do M3 têm mais variações do que os equivalentes no M2. Em geral, as superfícies da API M3 tentam ser o mais semelhante possível aos equivalentes mais próximos no M2.
Considerando os sistemas de cor, tipografia e forma atualizados, os componentes do M3 tendem a ser mapeados de maneira diferente dos novos valores de tema. É recomendável conferir o diretório de tokens no código-fonte do Compose Material 3 como uma fonte de verdade para esses mapeamentos.
Embora alguns componentes exijam considerações especiais, os mapeamentos de funções abaixo são recomendados como ponto de partida:
APIs ausentes:
M2 | M3 |
---|---|
androidx.compose.material.swipeable |
Ainda não disponível |
APIs substituídas:
M2 | M3 |
---|---|
androidx.compose.material.BackdropScaffold |
Nenhum equivalente do M3. Migre para o Scaffold ou o BottomSheetScaffold |
androidx.compose.material.BottomDrawer |
Sem equivalente do M3, migre para ModalBottomSheet |
APIs renomeadas:
Todas as outras APIs:
Consulte os componentes e layouts mais recentes do M3 na Visão geral da Referência da API Compose Material 3 e fique de olho na página de lançamentos para APIs novas e atualizadas.
Scaffold, snackbars e gaveta de navegação
O Scaffold no M3 é diferente do M2. Nas versões M2 e M3, o principal elemento combinável de layout
é chamado Scaffold
, mas os pacotes e parâmetros de importação são diferentes:
M2
import androidx.compose.material.Scaffold
Scaffold(
// M2 scaffold parameters
)
M3
import androidx.compose.material3.Scaffold
Scaffold(
// M3 scaffold parameters
)
O Scaffold
do M2 que contém um parâmetro backgroundColor
agora é chamado de
containerColor
no Scaffold
do M3:
M2
import androidx.compose.material.Scaffold
Scaffold(
backgroundColor = …,
content = { … }
)
M3
import androidx.compose.material3.Scaffold
Scaffold(
containerColor = …,
content = { … }
)
A classe ScaffoldState
do M2 não existe mais no M3 porque contém um parâmetro
drawerState
que não é mais necessário. Para mostrar snackbars com
o Scaffold
do M3, use 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(…)
}
}
)
Todos os parâmetros drawer*
do Scaffold
do M2 foram removidos
do Scaffold
do M3. Isso inclui parâmetros como drawerShape
e
drawerContent
. Para mostrar uma gaveta com o Scaffold
do M3, use um elemento combinável de gaveta
de navegação, 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 de apps superior
As principais barras de apps (link em inglês) no M3 são diferentes das usadas no M2. No M2
e no M3, o principal elemento combinável da barra de apps principal é chamado de TopAppBar
, mas os pacotes
e parâmetros de importação são diferentes:
M2
import androidx.compose.material.TopAppBar
TopAppBar(…)
M3
import androidx.compose.material3.TopAppBar
TopAppBar(…)
Considere usar o CenterAlignedTopAppBar
do M3 se já estiver
centralizando o conteúdo no TopAppBar
do M2. Também é bom conhecer o
MediumTopAppBar
e o LargeTopAppBar
.
As principais barras de apps do M3 contêm um novo parâmetro scrollBehavior
para fornecer diferentes
funcionalidades de rolagem pela classe TopAppBarScrollBehavior
, como
mudança da elevação. Isso funciona junto com a rolagem de conteúdo usando
Modifer.nestedScroll
. Isso foi possível no TopAppBar
do M2
mudando manualmente o parâmetro 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 { … }
}
)
Navegação inferior/barra de navegação
A navegação inferior no M2 foi renomeada como barra de navegação (link em inglês) no
M3. O M2 usa os elementos combináveis
BottomNavigation
e BottomNavigationItem
. O M3 usa os elementos combináveis
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(…)
}
Botões, botões de ícone e FABs
Botões, botões de ícone e botões de ação flutuante (FABs) (link em inglês) no M3 são diferentes dos botões no M2. O M3 inclui todos os elementos combináveis do botão do 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(…)
O M3 também inclui novas variações de botões. Confira-as na Visão geral de referência da API do Compose Material 3.
Chave
A chave (link em inglês) no M3 é diferente do M2. Tanto no M2 quanto no M3, a chave
de composição é chamada de Switch
, mas os pacotes de importação são diferentes:
M2
import androidx.compose.material.Switch
Switch(…)
M3
import androidx.compose.material3.Switch
Switch(…)
Superfícies e elevação
Os sistemas de superfície e elevação no M3 são diferentes do M2. Há dois tipos de elevação no M3:
- Elevação da sombra (gera uma sombra, igual à do M2)
- Elevação de tonalidade (sobreposição de uma cor, novidade do M3)
No Compose, isso se aplica às funções Surface
do M2 e
Surface
do M3:
M2
import androidx.compose.material.Surface
Surface(
elevation = …
) { … }
M3
import androidx.compose.material3.Surface
Surface(
shadowElevation = …,
tonalElevation = …
) { … }
Você pode usar os valores Dp
do elevation
no M2 para shadowElevation
e/ou tonalElevation
no M3, dependendo da preferência de design da UX/IU.
O Surface
é o elemento de apoio da maioria dos componentes.
Os elementos combináveis também podem expor parâmetros de elevação que precisam ser migrados da mesma
forma.
A elevação de tons no M3 substitui o conceito de sobreposições de elevação em temas escuros
M2. Como resultado, ElevationOverlay
e LocalElevationOverlay
não existem no M3, e LocalAbsoluteElevation
do M2 mudou para
LocalAbsoluteTonalElevation
no M3.
Ênfase e conteúdo Alfa
A ênfase no M3 é significativamente diferente do M2. No M2, a ênfase envolvia o uso de cores on com determinados valores Alfa para diferenciar conteúdo como texto e ícones. No M3, agora existem algumas abordagens diferentes:
- Usando cores on com as cores variante on do sistema de cores expandido do M3.
- Usar diferentes pesos de fonte para texto.
Como resultado, ContentAlpha
e LocalContentAlpha
não existem no
M3 e precisam ser substituídos.
Os mapeamentos abaixo são recomendados como ponto de partida:
M2 | M3 |
---|---|
onSurface por ContentAlpha.high |
onSurface em geral, FontWeight.Medium - FontWeight.Black para texto |
onSurface por ContentAlpha.medium |
onSurfaceVariant em geral, FontWeight.Thin - FontWeight.Normal para texto |
onSurface por ContentAlpha.disabled |
onSurface.copy(alpha = 0.38f) |
Confira um exemplo de ênfase de ícones no M2 e no 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(…)
}
Confira exemplos de ênfase no texto no 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
)
}
Planos de fundo e contêineres
Os planos de fundo no M2 são contêineres nomeados no M3. Em geral, é possível substituir
os parâmetros background*
no M2 por container*
no M3, usando os mesmos valores.
Exemplo:
M2
Badge(
backgroundColor = MaterialTheme.colors.primary
) { … }
M3
Badge(
containerColor = MaterialTheme.colorScheme.primary
) { … }
Links úteis
Para saber mais sobre a migração do M2 para o M3 no Compose, consulte os recursos abaixo.
Documentos
Apps de exemplo
- App de exemplo Reply no M3
- Migração do app Jetchat de exemplo do M2 para o M3
- Migração do app de exemplo Jetnews do M2 para o M3
- App principal Now in Android no M3 com o módulo :core-designsystem
Vídeos
Referência da API e código-fonte
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Material Design 2 no Compose
- Material Design 3 no Compose
- Sistemas de design personalizados no Compose