1. Antes de começar
O Material Design (link em inglês) é um sistema de design criado pelo Google para desenvolver experiências digitais de alta qualidade no Android e em outras plataformas da Web e de dispositivos móveis. Ele é inspirado no mundo real e nas texturas dele, incluindo a forma como os objetos refletem a luz e projetam sombras. Ele apresenta diretrizes sobre como criar a IU do app de uma forma legível, atraente e consistente.
Neste codelab, você vai aprender sobre os Temas do Material Design (link em inglês), que permitem usar esse sistema no seu app, com orientações sobre personalização de cores, tipografia e formas. É possível personalizar o quanto quiser. Você também vai aprender a adicionar uma barra de apps na parte de cima para mostrar o nome e o ícone do app.
Pré-requisitos
- Familiaridade com a linguagem Kotlin, incluindo sintaxe, funções e variáveis.
- Saber criar layouts no Compose, incluindo linhas e colunas com padding.
- Saber criar listas simples no Compose.
O que você vai aprender
- Como aplicar os temas do Material Design a um app do Compose.
- Como adicionar fontes personalizadas ao app.
- Como adicionar uma paleta de cores personalizada ao app.
- Como adicionar formas personalizadas a elementos no app.
- Como adicionar uma barra de apps à parte de cima do aplicativo.
O que você vai criar
- Você vai criar um belo app que incorpora as práticas recomendadas do Material Design.
O que é necessário
- Ter a versão mais recente do Android Studio.
- Uma conexão de Internet para fazer o download do código inicial e das fontes.
2. Assistir ao vídeo de orientações (opcional)
Se você quiser acompanhar a conclusão deste codelab por um dos instrutores do curso, assista ao vídeo abaixo.
Recomendamos abrir o vídeo em tela cheia usando o ícone no canto inferior direito da reprodução. Assim, você vê o Android Studio e o código com maior clareza.
Esta etapa é opcional. Você pode pular o vídeo e começar a seguir as instruções do codelab.
3. Visão geral do app
Neste codelab, você vai criar o Woof, um app que mostra uma lista de cachorros e usa o Material Design para criar uma bela experiência.
No app Woof, trabalhamos com um designer para ajudar a escolher a paleta de cores, a tipografia e as formas. Sabemos que nem todos têm acesso a um profissional, mas neste codelab vamos mostrar o que é possível fazer usando os temas do Material Design. Use este codelab para ter ideias sobre o uso dos temas do Material Design e melhorar a aparência dos apps que você criar.
Confira abaixo as especificações do nosso designer, que detalham o visual do app nos temas claro e escuro.
Design do app:
Tema claro | Tema escuro |
Paleta de cores
Confira abaixo a paleta de cores que o designer escolheu para os temas claro e escuro.
Tema claro:
Cor | Nome | Cor hexadecimal | Slot |
Cinza50 | #F8F9FA | principal | |
Verde50 | #E6F4EA | superfície | |
Verde100 | #CEEAD6 | segundo plano | |
Cinza700 | #5F6368 | secundário | |
Cinza900 | #202124 | onSurface | |
Cinza900 | #202124 | onPrimary |
Tema escuro:
Cor | Nome | Cor hexadecimal | Slot |
Branco | #FFFFFF | principal | |
Cinza100 | #F1F3F4 | onSurface | |
Cinza100 | #F1F3F4 | onPrimary | |
Ciano700 | #129EAF | superfície | |
Ciano900 | #007B83 | segundo plano | |
Cinza900 | #202124 | secundário |
Tipografia
Confira abaixo as fontes que o designer escolheu para o app.
Título | Fonte | Espessura da fonte | Tamanho |
h1 | Normal | 30sp | |
h2 | Negrito | 20sp | |
h3 | Negrito | 14 sp | |
body1 | Normal | 14 sp |
Arquivo de tema
O arquivo Theme.kt contém todas as informações sobre o tema do app, definidas por cor, tipografia e forma. Neste codelab, você vai fazer modificações nele apenas uma vez, mas é importante que você conheça esse arquivo. Dentro dele está o WoofTheme()
de composição, que define as cores, a tipografia e as formas do app.
@Composable
fun WoofTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
Em MainActivity.kt, o WoofTheme()
é adicionado para oferecer os temas do Material Design.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
WoofTheme {
WoofApp()
}
}
}
}
Dê uma olhada na DefaultPreview()
. O WoofTheme()
também é adicionado para oferecer os temas do Material Design mostrados na guia Preview.
@Preview
@Composable
fun DefaultPreview() {
WoofTheme(darkTheme = false) {
WoofApp()
}
}
4. Acessar o código inicial
- Navegue até a página do repositório do GitHub fornecida para o projeto.
- Clique no botão Code. Uma caixa de diálogo será aberta.
- Na caixa de diálogo, clique na guia HTTPS e, em seguida, em
ao lado do URL para copiá-lo. Esse URL será usado no Android Studio.
- Abra o Android Studio, se ele ainda não estiver aberto, e clique em Get from VCS, na janela Welcome to Android Studio.
- Se o Android Studio já estiver aberto, selecione File > New > Project from Version Control…
- Na janela Git from Version Control, selecione Git no menu Version control.
- Na caixa de texto de URL, digite o link que você copiou da página do repositório do GitHub.
- No menu Directory, selecione o diretório em que você quer clonar o código-fonte do repositório do GitHub.
- Clique em Clone.
- Espere o Android Studio fazer o download e abrir o projeto.
- No menu de navegação do Android Studio, clique em
Run app e confira se o app é criado da maneira esperada.
- No menu de navegação, clique em Git > Branches…
- Na caixa de diálogo Git Branches, na seção Remote Branches, selecione o nome da ramificação fornecido anteriormente e clique em Checkout.
- Caso precise trocar de ramificação, clique em Git > Branches e selecione aquela que você quer usar. Em seguida, clique em Smart Checkout.
Analisar o código inicial
- Abra o código inicial no Android Studio.
- Abra com.example.woof > data > Dog.kt. O arquivo contém a classe
Dog data class
que vai ser usada para representar a foto, o nome, a idade e os hobbies do cachorro. Ele também contém uma lista de cachorros e as informações que você vai usar como dados no app. - Abra res > drawable. Ele contém todos os recursos de imagem necessários para este projeto, incluindo o ícone do app e os ícones e imagens de cachorros.
- Abra res > values > strings.xml. Ele contém as strings que você vai usar no app, incluindo o nome do aplicativo, os nomes dos cachorros, as descrições e muito mais.
- Abra MainActivity.kt. Ele contém o código para criar uma lista simples com a foto de um cachorro, o nome e a idade dele.
WoofApp()
contém umaLazyColumn
que mostra osDogItems
.DogItem()
contém umaRow
que mostra uma foto do cachorro e informações sobre ele.DogIcon()
mostra uma foto do cachorro.DogInformation()
contém o nome e a idade do cachorro.
Conferir se o emulador/dispositivo está no tema claro
Neste codelab, você vai trabalhar com os temas claro e escuro, mas a maior parte do guia foca no tema claro. Antes de começar, confira se o dispositivo/emulador está no tema claro.
Para conferir o app no tema claro, siga estas etapas no emulador ou dispositivo físico:
- Acesse o app Configurações.
- Pesquise Tema escuro e clique nessa opção.
- Se ele estiver ativado, desative o Tema escuro.
Execute o código inicial para conferir como as coisas estão no começo. O app é uma lista que mostra cachorros, com fotos, nomes e idades. Ele funciona, mas não tem uma aparência muito boa. Vamos cuidar disso.
5. Adicionar cores
A primeira coisa que você vai modificar no app Woof é a paleta de cores.
Uma paleta é a combinação de cores que o app usa. Combinações diferentes evocam sensações diferentes, o que influencia as reações das pessoas quando usam o app. Como trabalhamos com um designer neste app, a paleta de cores foi escolhida por um profissional. No entanto, o site do Material Design oferece orientações do sistema de cores (link em inglês) para que você possa saber mais sobre paletas e aprender a gerar uma.
Ao adicionar uma cor ao seu app Android, você usou algo como Color.RED
ou Color.PINK
. E se você quiser adicionar uma cor mais específica, como azul-celeste ou verde jade?
No sistema Android, a cor é representada por um valor hexadecimal (hex). Um código de cor hexadecimal começa com uma cerquilha (#) e é seguido por seis letras e/ou números que representam os componentes vermelho, verde e azul (RGB) dessa cor. As duas primeiras letras/números se referem ao vermelho, as duas seguintes ao verde e as duas últimas ao azul.
Uma cor também pode incluir um valor alfa (letras e/ou números) representando a transparência: #00 indica 0% de opacidade, ou seja, totalmente transparente, e #FF indica 100% de opacidade, ou seja, totalmente opaco. Quando incluído, o valor alfa é composto pelos primeiros dois caracteres do código de cor hexadecimal após o caractere cerquilha (#). Se não houver um valor alfa, ele vai ser considerado #FF, que indica 100% de opacidade (totalmente opaco).
Confira abaixo alguns exemplos de valores de cores hexadecimais.
Cor | Nome | Cor hexadecimal |
Preto | #000000 | |
Verde | #72D98C | |
Azul | #4285F4 | |
Branco | #FFFFFF |
Não é necessário se lembrar dos códigos de cor hexadecimais, é claro. Existem ferramentas para escolher as cores (link em inglês) que geram os números para você. Neste codelab, temos algumas sugestões.
Confira abaixo a paleta usada no app. Não há um valor alfa, o que significa que as cores têm 100% de opacidade.
Tema claro:
Cor | Nome | Cor hexadecimal | Slot |
Cinza50 | #F8F9FA | principal | |
Verde50 | #E6F4EA | superfície | |
Verde100 | #CEEAD6 | segundo plano | |
Cinza700 | #5F6368 | secundário | |
Cinza900 | #202124 | onSurface | |
Cinza900 | #202124 | onPrimary |
Você pode se perguntar o que são slots e como eles são atribuídos.
- A cor principal é a cor mostrada com mais frequência nas telas e componentes do app.
- A cor secundária oferece mais formas de destacar e diferenciar seu app.
- A cor da superfície afeta superfícies de componentes, como cards, páginas e menus.
- A cor de segundo plano aparece atrás do conteúdo rolável.
- Os elementos de cor on aparecem sobre as outras cores da paleta e são aplicados principalmente a textos, iconografia e traços. Temos também uma cor onSurface, que aparece por cima da cor de superfície, e uma cor onPrimary, que aparece por cima da cor principal.
Esses slots oferecem um sistema de design coeso em que os componentes relacionados são coloridos de forma semelhante.
Alguns componentes são mapeados automaticamente para os slots de cor. Por exemplo, as Surface
de composição têm a cor de fundo mapeada automaticamente para o slot da superfície. Isso significa que você não precisa atribuir explicitamente uma cor de superfície à Surface
de composição. Ela vai aparecer dessa forma automaticamente quando você definir o tema de cores do app. Há mais slots de cor do que esses seis, mas não é necessário atribuir todos eles. Todas as cores que não estiverem especificadas no tema do app vão seguir automaticamente o tema de referência do Material Design (link em inglês), que define um tema padrão para o app.
Mas chega de falar de teoria. Hora de adicionar essa bela paleta de cores ao app.
Adicionar a paleta de cores ao tema
- Abra o arquivo Color.kt. Esse arquivo é usado para adicionar cores à paleta do app. Algumas cores já foram adicionadas para mapear a paleta ao padrão. Adicione cores novas à paleta do app Woof abaixo das já incluídas.
//Light Theme
val Grey50 = Color(0xFFF8F9FA)
val Grey900 = Color(0xFF202124)
val Grey700 = Color(0xFF5F6368)
val Green50 = Color(0xFFE6F4EA)
val Green100 = Color(0xFFCEEAD6)
- Abra o arquivo Theme.kt e substitua
LightColorPalette
pelo código abaixo, adicionando as cores aos slots.
private val LightColorPalette = lightColors(
background = Green100,
surface = Green50,
onSurface = Grey900,
primary = Grey50,
onPrimary = Grey900,
secondary = Grey700
)
O método WoofTheme()
vai conferir se darkTheme
está definido como verdadeiro ou não. Além disso, vai definir as colors
no MaterialTheme
object
como a paleta de cores clara se o valor de darkTheme for falso ou como a paleta de cores escura, se for verdadeiro.
@Composable
fun WoofTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
Adicionar cores ao app
Agora que as cores foram adicionadas, é hora de aproveitá-las em diferentes áreas do app. Você vai usar o seguinte:
- A cor
background
para o segundo plano da lista. - A cor
surface
para o segundo plano do item para que ele se destaque da cor do segundo plano da lista. - A cor
onSurface
para o texto, para que seja fácil ler o item na lista.
As outras duas cores vão ser usadas mais tarde no codelab.
- Abra MainActivity.kt. Em
WoofApp()
, adicione um modificador de segundo plano aoLazyColumn
para tornar o segundo plano da lista verde. Defina a cor do segundo plano como a cor definida embackground
no Theme.kt. Você pode acessar a cor definida como a corbackground
do tema do app usandoMaterialTheme.colors.background
. - Clique em Build & Refresh na guia Preview.
import androidx.compose.material.MaterialTheme
import androidx.compose.foundation.background
LazyColumn(modifier =
Modifier.background(MaterialTheme.colors.background))
Bom trabalho! O segundo plano agora tem a cor Green100
.
- No
DogItem()
, adicione uma extensãobackground()
àRow
e transmita paraMaterialTheme.colors.surface
. Isso vai definir a cor do segundo plano daRow
para usar a corsurface
especificada no tema do app.
import androidx.compose.ui.unit.dp
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.background(MaterialTheme.colors.surface)
)
Na guia Preview, você vai notar que o item da lista agora tem uma cor diferente do segundo plano do app, e cada item está mais distinto.
- No método
DogInformation()
, adicione acolor
aos elementos de composição dos textos de nome e idade dos cachorros. Isso vai mudar a cor da fonte dos dois elementos de composição de texto. Use a coronSurface
.
Column {
Text(
text = stringResource(dog.name),
color = MaterialTheme.colors.onSurface,
modifier = Modifier.padding(top = smallPadding)
)
Text(
text = stringResource(R.string.years_old, dog.age.toString()),
color = MaterialTheme.colors.onSurface
)
}
- Crie e atualize o app. O texto que mostra o nome e a idade dos cachorros agora tem mais contraste em relação ao segundo plano e é mais fácil de ler, mas isso não fica tão óbvio no tema claro.
Tema claro:
Confira abaixo o contraste do texto em relação ao segundo plano no tema escuro, que vai ser implementado na próxima seção:
Tema escuro sem cor para o texto | Tema escuro com cor para o texto |
Tema escuro
No sistema Android, você tem a opção de colocar o dispositivo no tema escuro. Um tema escuro usa cores mais escuras e discretas e:
- Pode reduzir significativamente o consumo de energia (dependendo da tecnologia da tela do dispositivo).
- Melhora a visibilidade para usuários com problemas de visão e que tenham sensibilidade ao brilho da luz.
- Facilita o uso do dispositivo em ambientes com pouca luz.
O app pode ativar o recurso Forçar modo escuro, que faz com que o sistema implemente um tema escuro para você. No entanto, os usuários vão ter uma experiência melhor se você implementar o tema escuro no app. Assim, você tem controle total sobre o tema do app.
Ao criar um tema escuro próprio, é importante lembrar que as cores dele precisam atender aos padrões de contraste de acessibilidade (link em inglês). Os temas escuros usam uma cor de superfície escura com tons de cores limitados.
Confira abaixo as cores do tema escuro do app:
Tema escuro:
Cor | Nome | Cor hexadecimal | Slot |
Branco | #FFFFFF | principal | |
Cinza100 | #F1F3F4 | onSurface | |
Cinza100 | #F1F3F4 | onPrimary | |
Ciano700 | #129EAF | superfície | |
Ciano900 | #007B83 | segundo plano | |
Cinza900 | #202124 | secundário |
Adicionar um tema escuro
- Em Color.kt, adicione as cores ao tema escuro. Você está adicionando apenas quatro cores porque
Grey900
já foi adicionado ao tema claro.
//Dark Theme
val White = Color(0xFFFFFFFF)
val Grey100 = Color(0xFFF1F3F4)
val Cyan900 = Color(0xFF007B83)
val Cyan700 = Color(0xFF129EAF)
- Remova as cores fornecidas por padrão, porque elas não vão mais ser necessárias. Confira abaixo os novos valores do arquivo.
//Light Theme
val Grey50 = Color(0xFFF8F9FA)
val Grey900 = Color(0xFF202124)
val Grey700 = Color(0xFF5F6368)
val Green50 = Color(0xFFE6F4EA)
val Green100 = Color(0xFFCEEAD6)
//Dark Theme
val White = Color(0xFFFFFFFF)
val Grey100 = Color(0xFFF1F3F4)
val Cyan900 = Color(0xFF007B83)
val Cyan700 = Color(0xFF129EAF)
- No arquivo Theme.kt, substitua a
DarkColorPalette
existente pelas cores mostradas abaixo.
private val DarkColorPalette = darkColors(
background = Cyan900,
surface = Cyan700,
onSurface = White,
primary = Grey900,
onPrimary = White,
secondary = Grey100
)
Conferir o tema escuro na visualização
Para conferir o tema escuro em ação, adicione outra Preview()
ao arquivo MainActivity.kt. Dessa forma, ao mudar o layout da IU no seu código, você vai poder conferir a aparência do tema claro e do tema escuro simultaneamente.
- Em
DefaultPreview()
, crie uma nova função com o nomeDarkThemePreview()
e faça uma anotação com@Preview
e@Composable
.
@Preview
@Composable
fun DarkThemePreview() {
}
- Em
DarkThemePreview()
, adicione oWoofTheme()
. Se o métodoWoofTheme()
não fosse adicionado, nenhum estilo que adicionamos apareceria no app. Defina o parâmetrodarkTheme
como true.
@Preview
@Composable
fun DarkThemePreview() {
WoofTheme(darkTheme = true) {
}
}
- Chame
WoofApp()
emWoofTheme()
.
@Preview
@Composable
fun DarkThemePreview() {
WoofTheme(darkTheme = true) {
WoofApp()
}
}
Agora, quando você clicar em Build & Refresh na seção Preview
e rolar para baixo, vai poder conferir o app no tema escuro, incluindo o segundo plano mais escuro do app/item da lista e o texto em branco. Você pode comparar as diferenças entre os temas claro e escuro.
Tema escuro | Tema claro |
Conferir o tema escuro no dispositivo ou emulador
Para visualizar o app no tema escuro no emulador ou dispositivo físico, siga estas etapas:
- Acesse o app Configurações.
- Pesquise tema escuro e clique nessa opção.
- Ative o Tema escuro.
- Abra o app Woof novamente com o tema escuro ativado.
Este codelab se concentra mais no tema claro. Portanto, antes de avançar, desative o tema escuro.
- Acesse o app Configurações.
- Selecione Tela.
- Desative o Tema escuro.
Compare a aparência do app quando começamos e a de agora. Os itens e texto da lista estão mais definidos, e o esquema de cores está mais bonito.
Sem cor | Com cor (tema claro) | Com cor (tema escuro) |
6. Adicionar formas
Por padrão, todas as formas do app são retangulares. No entanto, aplicar uma forma pode mudar muito a aparência de um elemento de composição. As formas podem ser usadas para chamar atenção, identificar os componentes, comunicar o estado e expressar a marca.
Muitas formas são definidas usando RoundedCornerShape
, que descreve um retângulo com cantos arredondados. O número transmitido define o quão redondos os cantos vão ser. Se RoundedCornerShape(percent = 0)
for usado, o retângulo não vai ter cantos arredondados. Se RoundedCornerShape(percent = 50)
for usado, os cantos vão ser totalmente circulares. Caso você queira testar formas mais complexas, o site do Material Design oferece uma ferramenta de personalização de formas (link em inglês).
0 por cento | 25 porcento | 50 por cento |
O arquivo Shape.kt é usado para definir formas de componentes no Compose. Existem três tipos de componentes: pequeno, médio e grande. Nesta seção, você vai modificar o componente Card
, que é definido por um tamanho medium
. Os componentes são agrupados em categorias de formas (link em inglês) com base no tamanho.
Como Image
não é um componente, você vai adicionar a forma dele em MainActivity.kt.
Nesta seção, você vai mudar a forma da imagem do cachorro para um círculo e modificar a forma do item da lista.
Transformar a imagem do cachorro em um círculo
- Primeiro, você vai modificar o ícone com a foto do cachorro para que ele seja redondo. Abra MainActivity.kt. Em
DogIcon()
, adicione um atributoclip
aomodifier
daImage
. Isso vai cortar a imagem em uma forma específica. TransmitaRoundedCornerShape()
como50
para que os cantos fiquem totalmente circulares.
import androidx.compose.ui.draw.clip
import androidx.compose.foundation.shape.RoundedCornerShape
@Composable
fun DogIcon(@DrawableRes dogIcon: Int, modifier: Modifier = Modifier) {
Image(
modifier = modifier
.size(64.dp)
.padding(8.dp)
.clip(RoundedCornerShape(50)),
Ao observar a DefaultPreview
, você vai perceber que os ícones dos cachorros agora são circulares. No entanto, algumas fotos estão cortadas nas laterais e não aparecem como círculos.
- Para tornar todas as fotos circulares, adicione atributos
ContentScale
eCrop
. A imagem vai ser cortada para caber no espaço disponível. Observe quecontentScale
é um atributo daImage
e não faz parte demodifier
.
import androidx.compose.ui.layout.ContentScale
@Composable
fun DogIcon(dogIcon: Int, modifier: Modifier = Modifier) {
Image(
modifier = modifier
.size(64.dp)
.padding(8.dp)
.clip(RoundedCornerShape(50)),
contentScale = ContentScale.Crop,
Agora, quando você executar o app, os ícones vão estar circulares.
Adicionar uma forma ao item da lista
Nesta seção, você vai adicionar uma forma ao item da lista. O item da lista já é mostrado em uma Row
, mas uma Row
não tem forma. Por isso, adicione a Row
a um Card
(link em inglês). Um Card
é uma superfície que pode conter um único elemento de composição, além de opções para decoração. A decoração pode ser adicionada pela borda, forma, elevação e muito mais. Nesta seção, você vai usar o Card
para adicionar uma forma ao item da lista.
- Em
DogItem()
, adicione umCard
ao redor daRow
.
import androidx.compose.material.Card
@Composable
fun DogItem(dog: Dog, modifier: Modifier = Modifier) {
Card() {
Row(
- Abra o arquivo Shape.kt. Um
Card
é um componente médio, então você precisa atualizar o atributo médio do objetoShapes
. Neste app, você vai arredondar os cantos da lista, mas não os deixe totalmente circulares. Para fazer isso, transmita16.dp
ao atributomedium
.
val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(16.dp),
large = RoundedCornerShape(0.dp)
)
- Como um
Card
, por padrão, já usa a forma média, você não precisa fazer uma definição explícita. Atualize a Preview para conferir os cantos arredondados. Os itens da lista não têm padding entre eles, e não fica claro onde um item termina e o próximo começa. Por isso, você vai adicionar padding entre os itens da lista para os diferenciar.
Ao retornar ao arquivo Theme.kt no WoofTheme()
e analisar o MaterialTheme()
, você vai notar que o atributo shapes
está definido como o val
Shapes
que você acabou de atualizar.
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
Atualizar modificadores e adicionar padding
- Como o
Card
agora é o primeiro elemento de composição que aparece noDogItem()
, o modificador transmitido para o elemento de composiçãoDogItem
precisa ser encaminhado para oCard
, e não para aRow
. ARow
agora usa uma nova instância doModifier
.
@Composable
fun DogItem(dog: Dog, modifier: Modifier = Modifier) {
Card(
modifier = modifier
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.background(MaterialTheme.colors.surface)
)
- Adicione
padding
aoCard modifier
e transmita8.dp
para adicionar padding ao redor de cada item da lista.
Card(
modifier = modifier.padding(8.dp)
)
Ao atualizar a Preview, você vai notar que é mais fácil distinguir os itens da lista com cantos arredondados devido ao padding entre eles.
Cores não explícitas
Um Card
é uma Surface
, e no arquivo Theme.kt temos uma cor definida explicitamente para o slot surface
. Por isso, podemos remover a cor da Row
sem precisar definir explicitamente a cor surface
.
- Em
DogItem()
, remova a configuração explícita da cor do segundo plano.
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
)
Atualize a Preview. Você vai notar que a Row
ainda tem a mesma cor do segundo plano, mesmo que tenhamos removido a atribuição de cores explícita.
- Como o
Text
do nome e da idade dos cachorros está acima de umaSurface
, a cor padrão éonSurface
. Remova a configuração de cor explícita dos dois itensText
emDogInformation()
.
Confira abaixo a aparência do elemento de composição:
@Composable
fun DogInformation(@StringRes dogName: Int, dogAge: Int, modifier: Modifier = Modifier) {
Column {
Text(
text = stringResource(dogName),
modifier = modifier.padding(top = 8.dp)
)
Text(
text = stringResource(R.string.years_old, dogAge)
)
}
}
Adicionar elevação ao item da lista
O app fica muito bom com as definições de forma nos itens da lista, mas vamos adicionar mais coisas para que os itens tenham mais contraste em relação ao segundo plano. Você já usou o atributo Card
shape
para moldar os itens da lista. Agora, o atributo Card
elevation
vai ser usado para adicionar elevação ao card. A elevação cria contraste entre o Card
e o segundo plano, adicionando uma sombra para tornar o app mais realista e interessante.
- Em
DogItem()
, adicionelist_item_elevation
como o atributoelevation
doCard
.
Card(
modifier = Modifier.padding(8.dp),
elevation = 4.dp
)
- Atualize a Preview. A elevação adiciona sombra e profundidade ao app, tornando a aparência mais realista.
Confira abaixo o app lado a lado, antes e depois da adição de formas. Observe como ele ficou mais bonito.
Sem formas | Com formas |
7. Adicionar tipografia
A escala de tipografia do Material Design
Uma escala de tipografia é uma seleção de estilos de fonte que podem ser usados em um app, garantindo um estilo flexível e consistente. A escala de tipografia do Material Design (link em inglês) inclui 13 estilos de fonte com suporte ao sistema de tipografia. Você só precisa usar essas opções caso queira personalizar o app. Se você não souber o que definir para cada categoria da escala, há uma escala de tipografia padrão que pode ser usada.
A escala de tipografia contém categorias reutilizáveis de texto, cada uma com uma intenção de aplicação e significado. No nosso app, vamos usar apenas as categorias de título e corpo de texto.
Títulos
Na escala de tipografia, os títulos variam em um intervalo de 1 a 6. Eles são o maior texto na tela, reservados para informações curtas e importantes ou números.
Corpo do texto
O corpo do texto varia em um intervalo de 1 a 2 e geralmente é usado para textos longos, porque funciona bem com tamanhos menores.
Fontes
A Plataforma Android oferece algumas fontes, mas você pode querer personalizar o app com uma fonte não fornecida por padrão. Fontes personalizadas podem adicionar personalidade e ser usadas para representar sua marca.
Nesta seção, você vai adicionar fontes personalizadas conhecidas como Abril Fatface, Montserrat Bold e Montserrat Regular. Você vai usar os títulos H1 e H2 e o corpo de texto body1 do sistema de tipografia do Material Design para o texto no app.
Criar uma fonte no diretório de recursos do Android.
Antes de adicionar fontes ao app, você vai precisar adicionar um diretório de fontes.
- Na visualização de projeto do Android Studio, clique com o botão direito do mouse na pasta res.
- Selecione New > Android Resource Directory.
- Nomeie o diretório como font, defina o tipo de recurso como font e clique em OK.
- Abra o novo diretório de recursos de fontes localizado em res > font.
Fazer o download de fontes personalizadas
Como você está usando fontes que não são fornecidas pela Plataforma Android, vai ser necessário fazer o download de fontes personalizadas.
- Acesse https://fonts.google.com/.
- Pesquise Montserrat e clique em Download family.
- Descompacte o arquivo ZIP.
- Abra a pasta Montserrat que você transferiu por download. Na pasta static, localize Montserrat-Bold.ttf e Montserrat-Regular.ttf (ttf significa TrueType Font e é o formato dos arquivos de fontes). Selecione os dois arquivos e arraste para o diretório de recursos de fontes do projeto no Android Studio.
- Na pasta de fontes, renomeie Montserrat-Bold.ttf como montserrat_bold.ttf e Montserrat-Regular.ttf como montserrat_regular.ttf.
- Pesquise Abril Fatface e clique em Download family.
- Abra a pasta Abril_Fatface. Selecione AbrilFatface-Regular.ttf e arraste para o diretório de recursos de fontes.
- Na pasta de fontes, renomeie Abril_Fatface_Regular.ttf como abril_fatface_regular.ttf.
O diretório de recursos de fontes do projeto vai ficar assim com os três arquivos de fontes personalizadas:
Inicializar fontes
- Na janela do projeto, abra ui.theme > Type.kt e exclua o conteúdo da variável
Typography
.
// Set of Material typography styles to start with
val Typography = Typography(
)
- Inicialize as fontes transferidas por download abaixo das instruções de importação e acima de
val
Typography
. Primeiro, inicialize Abril Fatface, definindo a fonte comoFontFamily
e transmitindoFont
com o arquivo de fonteabril_fatface_regular
.
val AbrilFatface = FontFamily(
Font(R.font.abril_fatface_regular)
)
- Inicialize Montserrat, abaixo de Abril Fatface, definindo a fonte como
FontFamily
e transmitindoFont
com o arquivo de fontemontserrat_regular
. Paramontserrat_bold
, inclua tambémFontWeight.Bold
. Mesmo que você transmita a versão em negrito do arquivo de fonte, o Compose não vai saber que o arquivo está em negrito. Portanto, faça a vinculação explícita deFontWeight.Bold
.
val AbrilFatface = FontFamily(
Font(R.font.abril_fatface_regular)
)
val Montserrat = FontFamily(
Font(R.font.montserrat_regular),
Font(R.font.montserrat_bold, FontWeight.Bold)
)
Em seguida, defina os diferentes tipos de título como as fontes que você acabou de adicionar. O objeto Typography
tem parâmetros para 13 tipos de fontes diferentes discutidos acima. Defina quantos forem necessários. Neste app, vamos definir h1
(Título 1), h2
(Título 2) e body1
(corpo de texto 1). Na próxima parte do app, você vai usar h3
(Título 3), então já vamos adicionar esse elemento agora.
Confira abaixo a tabela da seção Visão geral do app, que mostra a fonte e o tamanho de cada título que você está adicionando.
Título | Fonte | Espessura da fonte | Tamanho |
h1 | Normal | 30sp | |
h2 | Negrito | 20sp | |
h3 | Negrito | 14 sp | |
body1 | Normal | 14 sp |
- Use a tabela acima para preencher o
val
Typography
. Defina o atributoh1
da mesma forma queTextStyle
e preenchafontFamily
,fontWeight
efontSize
com as informações da tabela acima. Isso significa que todo o texto definido comoh1
terá Abril Fatface como a fonte definida, com uma espessura de fonte normal e umfontSize
de30.sp
.
Repita esse processo para h2
, h3
e body1
.
val Typography = Typography(
h1 = TextStyle(
fontFamily = AbrilFatface,
fontWeight = FontWeight.Normal,
fontSize = 30.sp
),
h2 = TextStyle(
fontFamily = Montserrat,
fontWeight = FontWeight.Bold,
fontSize = 20.sp
),
h3 = TextStyle(
fontFamily = Montserrat,
fontWeight = FontWeight.Bold,
fontSize = 14.sp
),
body1 = TextStyle(
fontFamily = Montserrat,
fontWeight = FontWeight.Normal,
fontSize = 14.sp
)
)
Ao retornar ao arquivo Theme.kt no WoofTheme()
e analisar o MaterialTheme()
, você vai notar que o atributo typography
foi definido como a Typography
val
que você acabou de atualizar.
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
Adicionar tipografia ao texto do app
Agora, você vai adicionar os tipos de título a cada instância de texto no app.
- Adicione
h2
como o estilo dedog name
, já que é uma informação curta e importante. Adicionebody1
como o estilo dedog age
, já que essa informação funciona bem com tamanhos de texto menores.
@Composable
fun DogInformation(@StringRes dogName: Int, dogAge: Int, modifier: Modifier = Modifier) {
Column {
Text(
text = stringResource(dogName),
style = MaterialTheme.typography.h2,
modifier = modifier.padding(top = 8.dp)
)
Text(
text = stringResource(R.string.years_old, dogAge),
style = MaterialTheme.typography.body1
)
}
}
- Atualize o app. Agora, o nome do cachorro usa a fonte Montserrat em negrito em
20.sp
, e a idade do cachorro aparece com a fonte Montserrat normal em14.sp
.
Confira abaixo o app lado a lado, antes e depois de adicionarmos a tipografia. Observe a diferença entre as fontes do nome e da idade dos cachorros.
Sem tipografia | Com tipografia |
8. Adicionar uma barra na parte de cima
Um Scaffold
é um layout que fornece slots para vários componentes e elementos de tela, como Image
, Row
ou Column
. Um Scaffold
também fornece um slot para uma topBar
, que vamos usar nesta seção.
Uma topBar
pode ser usada para muitos objetivos, mas neste caso você vai fazer o branding e dar uma personalidade ao app. Você vai criar um elemento de composição semelhante à captura de tela abaixo na seção topBar
de um Scaffold
.
Neste app, a barra de cima consiste em uma linha com um logotipo e o título do app. O logotipo mostra uma pata em gradiente e o título do app.
Adicionar imagem e texto à barra de cima
- Em MainActivity.kt, crie um elemento de composição com o nome
WoofTopAppBar()
que aceita ummodifier
.
@Composable
fun WoofTopAppBar(modifier: Modifier = Modifier) {
}
- Em
WoofTopAppBar()
, adicione umaRow()
.
@Composable
fun WoofTopAppBar(modifier: Modifier = Modifier) {
Row() {
}
}
- Adicione uma
Image
àRow
. Usepainter
para definir aImage
comoic_woof_logo
da pasta de drawables e defina acontentDescription
como null. Neste caso, o logotipo do app não adiciona informações semânticas para usuários com problemas de visão. Portanto, não precisamos adicionar uma descrição de conteúdo.
Image(
painter = painterResource(R.drawable.ic_woof_logo),
contentDescription = null
)
- Em seguida, adicione um elemento de composição
Text
dentro daRow
depois daImage
e usestringResource()
para definir esse elemento como o valor deapp_name
. Isso define o texto como o nome do app, que é armazenado emstrings.xml
.
Text(
text = stringResource(R.string.app_name)
)
- Agora que você adicionou o ícone e o nome do app à
TopAppBar()
, é necessário adicionar aTopAppBar()
ao layout. EmWoofApp()
, adicione umScaffold
em volta daLazyColumn
.
import androidx.compose.material.Scaffold
@Composable
fun WoofApp() {
Scaffold(
) {
LazyColumn(modifier =
Modifier.background(MaterialTheme.colors.background)) {
items(dogs) {
DogItem(dog = it)
}
}
}
}
- No
Scaffold
, adicione um atributotopBar
e o defina comoWoofTopAppBar()
.
Scaffold(
topBar = {
WoofTopAppBar()
}
)
Confira abaixo a aparência do elemento de composição WoofApp()
:
@Composable
fun WoofApp() {
Scaffold(
topBar = {
WoofTopAppBar()
}
) {
LazyColumn(modifier = Modifier.background(MaterialTheme.colors.background)) {
items(dogs) {
DogItem(dog = it)
}
}
}
}
- Atualize a Preview e confira a barra de apps na parte de cima. Ela mostra o ícone e o texto, mas ainda não parece ser o produto final que queremos. Na próxima seção, você vai melhorar o visual dela usando cores, tipografia, padding e muito mais.
Deixar a barra de cima mais bonita
- Primeiro, vamos adicionar uma cor de segundo plano à barra de cima para a diferenciar do restante do app. Em
WoofTopAppBar()
, adicione a cor principal do tema do app como a cor do segundo plano. Para isso, adicione ummodifier
àRow
e defina a cor do segundo plano comoprimary
.
Row(
modifier = modifier
.background(color = MaterialTheme.colors.primary)
){ }
- A cor do segundo plano só aparece atrás do ícone e do texto, mas ela precisa cobrir toda a extensão do app. Para fazer isso, defina o
modifier
naRow
comofillMaxWidth()
.
Row(
modifier = modifier
.fillMaxWidth()
.background(color = MaterialTheme.colors.primary)
){ }
- Em seguida, atualize o texto para seguir o estilo
h1
(Título 1) definido anteriormente. Como o segundo plano está definido com a corprimary
, o texto vai ser definido automaticamente com a coronPrimary
.
Text(
text = stringResource(R.string.app_name),
style = MaterialTheme.typography.h1
)
- Já está melhorando muito, mas a imagem é muito pequena e vai ficar melhor ainda com padding. Adicione um modificador à
Image
e defina o tamanho da imagem como64.dp
e o padding em volta dela como8.dp
.
Image(
modifier = Modifier
.size(64.dp)
.padding(8.dp),
painter = painterResource(R.drawable.ic_woof_logo),
contentDescription = null
)
- Quase lá! Agora, defina o alinhamento vertical como
Alignment.CenterVertically
, que centraliza todos os itens na linha.
import androidx.compose.ui.Alignment
Row(
modifier = modifier
.fillMaxWidth()
.background(color = MaterialTheme.colors.primary),
verticalAlignment = Alignment.CenterVertically
){ }
Execute o app e confira como a TopAppBar
dá um toque final perfeito.
Sem a barra de apps na parte de cima | Com a barra de apps na parte de cima |
Agora, execute o app no tema escuro. Como a barra usa a cor primary
, e o texto usa a cor onSurface
, você não precisa atualizar nada no tema escuro.
Parabéns, você chegou ao fim do codelab.
9. [Opcional] Mudar a barra de status
Para melhorar ainda mais a experiência do usuário, você pode atualizar a cor da barra de status, que contém informações como horário, conexão de Internet, status da bateria e muito mais.
- Navegue até app > res > values > colors.xml.
- Exclua o conteúdo da tag
<resources>
.
<resources>
</resources>
- Adicione
grey_50
e defina a cor como#FFF8F9FA
para a barra de status do tema claro. Em seguida, adicionegrey_900
e defina a cor como#FF202124
para a barra de status do tema escuro.
<resources>
<color name="grey_50">#FFF8F9FA</color>
<color name="grey_900">#FF202124</color>
</resources>
- Navegue até app > res > values > themes.xml e substitua a cor em
android:statusBarColor
porgrey_50
<resources>
<style name="Theme.Woof" parent="android:Theme.Material.Light.NoActionBar">
<item name="android:statusBarColor">@color/grey_50</item>
</style>
</resources>
- Execute o app no dispositivo ou emulador.
A barra de status agora corresponde à barra de apps na parte de cima, tornando o esquema de cores mais unificado. O problema é que ficou difícil ver os ícones.
- No arquivo themes.xml, adicione
windowLightStatusBar
e defina como true emstatusBarColor
.
<resources>
<style name="Theme.Woof" parent="android:Theme.Material.Light.NoActionBar">
<item name="android:statusBarColor">@color/grey_50</item>
<item name="android:windowLightStatusBar">true</item>
</style>
</resources>
- Você vai receber uma mensagem de erro. Passe o cursor sobre a mensagem e pressione Override Resources in values-v23.
- Isso vai criar um novo arquivo themes.xml com o nome v23/themes.xml. Ele é usado no nível 23 da API e em versões mais recentes.
- Execute o app no emulador. Agora você pode conferir os ícones.
Adicionar uma barra de status no tema escuro
Agora você vai personalizar a barra de status no tema escuro.
- Na pasta res, adicione um novo diretório de recursos do Android com o nome values-night.
- Alterne para a visualização Project Source Files.
- Navegue até app > src > main > res > values-night.
- Em values-night, adicione um Values Resource File com o nome
themes.xml
. - Adicione uma tag de estilo com o nome
Theme.Woof
e o pai comoandroid:style/Theme.Material.NoActionBar
.
<resources>
<style name="Theme.Woof" parent="android:style/Theme.Material.NoActionBar">
</style>
</resources>
- Adicione a cor da barra de status como
grey_900
. Como ícones brancos são usados por padrão, não é necessário adicionar owindowsStatusLightBar
.
<resources>
<style name="Theme.Woof" parent="android:style/Theme.Material.NoActionBar">
<item name="android:statusBarColor">@color/grey_900</item>
</style>
</resources>
- Execute o app no tema escuro para conferir a atualização da barra de status.
10. Acessar o código da solução
Para fazer o download do código do codelab concluído, use estes comandos git:
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-woof.git $ cd basic-android-kotlin-compose-training-woof $ git checkout material
Se preferir, você pode fazer o download do repositório como um arquivo ZIP, descompactar e abrir no Android Studio.
Se você quiser ver o código da solução, acesse o GitHub (link em inglês).
11. Conclusão
Você acabou de criar seu primeiro app do Material Design. Você adicionou uma paleta de cores personalizada para os temas claro e escuro, criou formas para diferentes componentes, fez o download de fontes e as adicionou ao app, além de ter criado uma ótima barra superior para finalizar o projeto. Aplique as habilidades aprendidas neste codelab e mude cores, formas e tipografias para deixar os apps do seu jeito.
Resumo
- Com os Temas do Material Design (link em inglês), você pode usar o Material Design no seu app com orientações sobre personalização de cores, tipografia e formas.
- No arquivo Theme.kt, o tema é definido por um elemento combinável chamado [nome do app]+Theme()—
WoofTheme()
no caso do app deste codelab. Dentro dessa função, oobject
MaterialTheme
definecolor
,typography
,shapes
econtent
do app. - Você pode listar as cores que usa no app em Colors.kt. Em seguida, em Theme.kt, você atribui as cores em
LightColorPalette
eDarkColorPalette
a slots específicos. Nem todos os slots precisam ser atribuídos. - O app pode ativar o recurso Forçar modo escuro, que faz com que o sistema implemente um tema escuro para você. No entanto, os usuários vão ter uma experiência melhor se você implementar o tema escuro no app. Assim, você tem controle total sobre o tema do app.
- Shapes.kt é onde você define as formas do app. Existem três tamanhos de formas (pequeno, médio, grande) e você pode especificar como os cantos vão ser arredondados.
- As formas podem ser usadas para chamar atenção, identificar os componentes, comunicar o estado e expressar a marca.
- Types.kt é onde você inicializa as fontes e atribui
fontFamily
,fontWeight
efontSize
para a escala de tipografia do Material Design. - A escala de tipografia do Material Design (link em inglês) inclui um intervalo de estilos contrastantes com suporte às necessidades e aos conteúdos do app. A escala de tipografia é uma combinação de 13 estilos com suporte ao sistema de tipografia.
12. Saiba mais
- Material Design (link em inglês)
- Temas do Material Design (link em inglês)
- Escala de tipografia do Material Design (link em inglês)
- Sistema de cores do Material Design (link em inglês)
- Formas do Material Design (link em inglês)
- Parâmetros modificadores
- Forçar modo escuro
- Padrões de contraste de acessibilidade (link em inglês)
- Clip
- ContentScale
- Cortar
- Card (link em inglês)
- Scaffold