O Material 3 Expressive é a próxima evolução do Material Design. Ele inclui temas, componentes e recursos de personalização atualizados, como cores dinâmicas.
Este guia se concentra na migração da biblioteca Jetpack do Wear Compose Material 2.5 (androidx.wear.compose) para a biblioteca Jetpack do Wear Compose Material 3 (androidx.wear.compose.material3) para apps.
Abordagens
Para migrar o código do app do M2.5 para o M3, siga a mesma abordagem descrita nas orientações para smartphones sobre a migração do Compose Material, em especial:
- Não use o M2.5 e o M3 em um único app de longo prazo.
- Não use mais as bibliotecas Horologist Composables, Compose Layout ou Compose Material. Em vez disso, use os componentes do M3.
- Adote uma abordagem em fases.
Dependências
O M3 tem um pacote e uma versão separados para o M2.5:
M2.5
implementation("androidx.wear.compose:compose-material:1.4.0")
M3
implementation("androidx.wear.compose:compose-material3:1.8.0-alpha02")
Confira as versões mais recentes do M3 na página de versões do Wear Compose.
A versão 1.8.0-alpha02 da biblioteca Wear Compose Foundation introduziu
alguns novos componentes projetados para funcionar com os componentes do Material 3.
Da mesma forma, o SwipeDismissableNavHost da biblioteca de navegação do Compose para Wear tem uma
animação atualizada ao ser executado no Wear OS 6 (nível 36 da API) ou mais recente. Ao
atualizar para a versão do Wear Compose Material 3, sugerimos também atualizar as bibliotecas
Wear Compose Foundation e Navigation:
implementation("androidx.wear.compose:compose-foundation:1.8.0-alpha02")
implementation("androidx.wear.compose:compose-navigation:1.8.0-alpha02")
Tema
Nas versões M2.5 e M3, o elemento combinável de tema é chamado de MaterialTheme, mas os
pacotes e parâmetros de importação são diferentes. No M3, o parâmetro Colors foi
renomeado como ColorScheme, e o MotionScheme foi introduzido para implementar
transições.
M2.5
import androidx.wear.compose.material.MaterialTheme
MaterialTheme(
colors = AppColors,
typography = AppTypography,
shapes = AppShapes,
content = content
)
M3
import androidx.wear.compose.material3.MaterialTheme // ... MaterialTheme( colorScheme = ColorScheme(), typography = Typography(), shapes = Shapes(), motionScheme = MotionScheme.standard(), content = { /*content here*/ } )
Cor
O sistema de cores no M3 é significativamente diferente do M2.5. 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.5, à classe ColorScheme do M3 e às funções relacionadas:
M2.5
import androidx.wear.compose.material.Colors
val appColorScheme: Colors = Colors(
// M2.5 Color parameters
)
M3
import androidx.wear.compose.material3.ColorScheme // ... val appColorScheme: ColorScheme = ColorScheme( // M3 ColorScheme parameters )
A tabela a seguir descreve as principais diferenças entre o M2.5 e o M3:
| M2.5 | M3 |
|---|---|
Colors |
Foi renomeado como ColorScheme |
| 13 cores | 29 cores |
| N/A | Novo tema de cores dinâmicas |
| N/A | Novas cores terciárias para mais expressão |
Tema de cores dinâmicas
Um novo recurso do M3 é o tema de cores dinâmicas (link em inglês). Se os usuários mudarem as cores do mostrador do relógio, as cores na interface vão mudar para combinar.
Use a função dynamicColorScheme para implementar o esquema de cores dinâmicas
e forneça um defaultColorScheme como substituto caso o esquema de cores dinâmicas
não esteja disponível.
@Composable fun myApp() { val dynamicColorScheme = dynamicColorScheme(LocalContext.current) MaterialTheme(colorScheme = dynamicColorScheme ?: myBrandColors) {} } internal val myBrandColors: ColorScheme = ColorScheme( /* Specify colors here */)
Tipografia
O sistema de tipografia (link em inglês) do M3 é diferente do M2.5 e inclui os seguintes recursos:
- Nove novos estilos de texto
- Fontes flexíveis, que permitem personalizar as escalas de tipo para diferentes pesos, larguras e arredondamentos
AnimatedText, que usa fontes flexíveis
M2.5
import androidx.wear.compose.material.Typography
val Typography = Typography(
// M2.5 TextStyle parameters
)
M3
import androidx.wear.compose.material3.Typography val Typography = Typography( // M3 TextStyle parameters )
Fontes flexíveis
As fontes flexíveis permitem que os designers especifiquem a largura e o peso do tipo para tamanhos específicos.
Estilos de texto
Os seguintes TextStyles estão disponíveis no M3. Eles são usados por padrão por vários componentes do M3.
| Tipografia | TextStyle |
|---|---|
| Display | displayLarge, displayMedium, displaySmall |
| Título | titleLarge, titleMedium, titleSmall |
| Marcador | labelLarge, labelMedium, labelSmall |
| Corpo | bodyLarge, bodyMedium, bodySmall, bodyExtraSmall |
| Numeral | numeralExtraLarge, numeralLarge, numeralMedium, numeralSmall, numeralExtraSmall |
| Arco | arcLarge, arcMedium, arcSmall |
Forma
O sistema de formas (link em inglês) no M3 é diferente do M2.5. O número de parâmetros de forma aumentou, eles são nomeados de forma diferente e são mapeados de forma diferente para os componentes do M3. Os seguintes tamanhos de formato estão disponíveis:
- Muito pequeno
- Pequeno
- Médio
- Grande
- Extragrande
No Compose, isso se aplica às classes Shapes do M2.5 e
Shapes do M3:
M2.5
import androidx.wear.compose.material.Shapes
val Shapes = Shapes(
// M2.5 Shapes parameters
)
M3
import androidx.wear.compose.material3.Shapes val Shapes = Shapes( // M3 Shapes parameters )
Use o mapeamento de parâmetros de formas de Migrar do Material 2 para o Material 3 no Compose como ponto de partida.
Transformação de formas
O M3 apresenta a transformação de formas: agora as formas se transformam em resposta às interações.
O comportamento de transformação de forma está disponível como uma variação em vários botões redondos. Confira a lista de botões que oferecem suporte à transformação de forma:
| Botões | Função de transformação de formas |
|---|---|
IconButton |
IconButtonDefaults.animatedShapes anima o botão de ícone ao ser pressionado |
IconToggleButton |
IconToggleButtonDefaults.animatedShapes anima o botão ativar/desativar de ícone ao pressionar e IconToggleButtonDefaults.variantAnimatedShapes anima o botão ativar/desativar de ícone ao pressionar e marcar/desmarcar |
TextButton |
TextButtonDefaults.animatedShapes anima o botão de texto ao ser pressionado |
TextToggleButton |
TextToggleButtonDefaults.animatedShapes anima o botão de alternância de texto ao pressionar, e TextToggleButtonDefaults.variantAnimatedShapes anima o botão de alternância de texto ao pressionar e marcar/desmarcar. |
Componentes e layout
A maioria dos componentes e layouts do M2.5 está disponível no M3. No entanto, alguns componentes e layouts do M3 não existiam no M2.5. Além disso, alguns componentes do M3 têm mais variações do que os equivalentes no M2.5.
Embora alguns componentes exijam considerações especiais, os mapeamentos de funções abaixo são recomendados como ponto de partida:
Confira uma lista de componentes comuns do Material 3 e os equivalentes do Material 2.5:
Por fim, uma lista de alguns componentes relevantes da biblioteca Wear Compose Foundation:
| Wear Compose Foundation: versão 1.8.0-alpha02 | |
|---|---|
| androidx.wear.compose.foundation.hierarchicalFocusGroup | Usado para anotar elementos combináveis em um aplicativo, para acompanhar a parte ativa da composição e coordenar o foco. |
| androidx.wear.compose.foundation.pager.HorizontalPager | Um pager de rolagem horizontal, criado com base nos componentes do Compose Foundation com melhorias específicas para o Wear OS para melhorar o desempenho e a adesão às diretrizes do Wear OS. |
| androidx.wear.compose.foundation.pager.VerticalPager | Um pager de rolagem vertical, criado com base nos componentes do Compose Foundation com melhorias específicas para o Wear OS, que melhoram o desempenho e a conformidade com as diretrizes do Wear OS. |
| androidx.wear.compose.foundation.lazy.TransformingLazyColumn | Pode ser usado em vez de ScalingLazyColumn para adicionar efeitos de transformação de rolagem a cada item. |
Botões
Os botões no M3 são diferentes do M2.5. O ícone do M2.5 foi substituído pelo
botão. A implementação de Button fornece valores padrão para Text,
maxLines e textAlign. Esses valores padrão podem ser substituídos no elemento
Text.
M2.5
import androidx.wear.compose.material.Chip
//M2.5 Buttons
Chip(...)
CompactChip(...)
Button(...)
M3
//M3 Buttons Button(onClick = { }){} CompactButton(onClick = { }){} IconButton(onClick = { }){} TextButton(onClick = { }){}
O M3 também inclui novas variações de botões. Confira as novidades na Visão geral de referência da API Compose Material 3.
O M3 apresenta um novo botão: EdgeButton. O EdgeButton está disponível em quatro
tamanhos diferentes: extrapequeno, pequeno, médio e grande. A implementação de EdgeButton fornece um valor padrão para maxLines, dependendo do tamanho, que pode ser personalizado.
Se você estiver usando TransformingLazyColumn ou ScalingLazyColumn, transmita o
EdgeButton para o ScreenScaffold para que ele se transforme, mudando de forma
com a rolagem, em vez de adicionar um EdgeButton como o item final da lista. Confira
o código a seguir para saber como usar EdgeButton com ScreenScaffold e
TransformingLazyColumn.
val state = rememberTransformingLazyColumnState() ScreenScaffold( scrollState = state, edgeButton = { EdgeButton( onClick = { }, modifier = Modifier.scrollable( state, orientation = Orientation.Vertical, reverseDirection = true, // Apply overscroll to the EdgeButton for proper scrolling behavior. overscrollEffect = rememberOverscrollEffect(), ), ) { Text(stringResource(R.string.show)) } }, ) { contentPadding -> TransformingLazyColumn(state = state, contentPadding = contentPadding) { // additional code here // ... } }
Scaffold
O Scaffold no M3 é diferente do M2.5. No M3, o AppScaffold e o novo elemento combinável
ScreenScaffold substituíram o Scaffold. AppScaffold e
ScreenScaffold definem o layout da estrutura de uma tela e coordenam as transições
dos componentes ScrollIndicator e TimeText.
O AppScaffold permite que elementos estáticos da tela, como TimeText, fiquem visíveis
durante transições no app, como o gesto de deslizar para fechar. Ele fornece um slot para o
conteúdo principal do aplicativo, que geralmente é fornecido por um componente de navegação,
como SwipeDismissableNavHost.
Você declara um AppScaffold para a atividade e usa um ScreenScaffold para cada
tela.
AppScaffold adiciona um componente TimeText padrão às telas. É possível
substituí-lo se você quiser personalizá-lo usando o parâmetro timeText.
M2.5
import androidx.wear.compose.material.Scaffold
Scaffold {...}
M3
AppScaffold { val navController = rememberSwipeDismissableNavController() SwipeDismissableNavHost( navController = navController, startDestination = "message_list" ) { composable("message_list") { MessageList(onMessageClick = { id -> navController.navigate("message_detail/$id") }) } composable("message_detail/{id}") { MessageDetail(id = it.arguments?.getString("id")!!) } } } } // Implementation of one of the screens in the navigation @Composable fun MessageDetail(id: String) { // .. Screen level content goes here val scrollState = rememberTransformingLazyColumnState() val transformationSpec = rememberTransformationSpec() ScreenScaffold( scrollState = scrollState, ) { contentPadding -> // Screen content goes here // ...
Se você estiver usando um HorizontalPager com HorizontalPageIndicator, migre para o HorizontalPagerScaffold. HorizontalPagerScaffold é
colocado em um AppScaffold. AppScaffold e HorizontalPagerScaffold definem
o layout da estrutura de um Pager e coordenam as transições dos
componentes HorizontalPageIndicator e TimeText.
O HorizontalPagerScaffold mostra o HorizontalPageIndicator no
centro da tela por padrão e coordena a exibição e ocultação de
TimeText e HorizontalPageIndicator de acordo com a paginação do Pager, que é determinada pelo PagerState.
Também há um novo componente AnimatedPage, que anima uma página em um
Pager com um efeito de dimensionamento e de scrim com base na posição.
AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPagerScaffold(pagerState = pagerState) { HorizontalPager( state = pagerState, flingBehavior = PagerScaffoldDefaults.snapWithSpringFlingBehavior( state = pagerState ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { val columnState = rememberTransformingLazyColumnState() val transformationSpec = rememberTransformationSpec() ScreenScaffold( scrollState = columnState, ) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding, ) { item { ListHeader( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding( ListHeaderDefaults.minimumTopListContentPadding ), transformation = SurfaceTransformation(transformationSpec), ) { Text(text = "Pager sample") } } item { Card( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding( CardDefaults.minimumVerticalListContentPadding ), transformation = SurfaceTransformation(transformationSpec), ) { if (page == 0) { Text(text = "Page #$page. Swipe right") } else { Text(text = "Page #$page. Swipe left and right") } } } } } } } } }
Por fim, o M3 apresenta um VerticalPagerScaffold que segue o mesmo
padrão do HorizontalPagerScaffold:
@Composable fun VerticalPagerScaffoldSample() { AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPagerScaffold(pagerState = pagerState) { VerticalPager( state = pagerState, flingBehavior = PagerScaffoldDefaults.snapWithSpringFlingBehavior( state = pagerState ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { Text(text = "Page #$page") Spacer(modifier = Modifier.height(8.dp)) Text(text = "Swipe up and down") } } } } } } }
Marcador de posição
Há algumas mudanças na API entre o M2.5 e o M3. O M3 oferece dois modificadores de marcador de posição:
Modifier.placeholder, que é desenhado em vez do conteúdo que ainda não foi carregado.- Um efeito de brilho de marcador de posição
Modifier.placeholderShimmer, que fornece um efeito de brilho de marcador de posição que é executado em um loop de animação enquanto aguarda o carregamento dos dados.
Consulte a tabela a seguir para ver outras mudanças no componente Placeholder.
| M2.5 | M3 |
|---|---|
PlaceholderState.startPlaceholderAnimation |
Foi removido |
PlaceholderState.placeholderProgression |
Foi removido |
PlaceholderState.isShowContent |
Substituído por PlaceholderState.isVisible (booleano invertido) |
PlaceholderState.isWipeOff |
Foi removido |
PlaceholderDefaults.painterWithPlaceholderOverlayBackgroundBrush |
Foi removido |
PlaceholderDefaults.placeholderBackgroundBrush |
Foi removido |
PlaceholderDefaults.placeholderChipColors |
Foi removido |
SwipeDismissableNavHost
SwipeDismissableNavHost faz parte de wear.compose.navigation. Quando esse
componente é usado com o M3, o MaterialTheme do M3 atualiza o
LocalSwipeToDismissBackgroundScrimColor e o
LocalSwipeToDismissContentScrimColor.
TransformingLazyColumn
O TransformingLazyColumn faz parte do androidx.wear.compose.foundation.lazy e
adiciona suporte para dimensionar e transformar animações em itens de lista durante a rolagem,
melhorando a experiência do usuário. É altamente recomendável que os apps migrem de
ScalingLazyColumn para TransformingLazyColumn.
Assim como ScalingLazyColumn, ele fornece
rememberTransformingLazyColumnState() para criar um
TransformingLazyColumnState que é lembrado em todas as composições.
Para adicionar animações de dimensionamento e transformação, adicione o seguinte a cada item da lista:
Modifier.transformedHeight, que permite calcular a altura transformada dos itens usando umTransformationSpec, você pode usarrememberTransformationSpec(), a menos que precise de mais personalização.- Um
SurfaceTransformation
Para verificar se o padding está correto na parte de cima e de baixo da lista, use o
modificador minimumVerticalContentPadding.
val columnState = rememberTransformingLazyColumnState() val transformationSpec = rememberTransformationSpec() ScreenScaffold( scrollState = columnState ) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding ) { item { ListHeader( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding), transformation = SurfaceTransformation(transformationSpec) ) { Text(text = "Header") } } // ... other items item { Button( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding), transformation = SurfaceTransformation(transformationSpec), onClick = { /* ... */ }, icon = { Icon( imageVector = Icons.Default.Build, contentDescription = "build", ) }, ) { Text( text = "Build", maxLines = 1, overflow = TextOverflow.Ellipsis, ) } } } }
Links úteis
Para saber mais sobre a migração do M2.5 para o M3 no Compose, consulte os recursos abaixo.