1. Antes de começar
Neste codelab, você vai aprender a adicionar imagens ao seu app usando um elemento combinável Image
.
Pré-requisitos
- Conhecimento básico sobre como criar e executar um app no Android Studio.
- Conhecimento básico sobre como adicionar elementos da IU. Por exemplo, elementos de texto que podem ser compostos.
O que você vai aprender
- Como adicionar uma imagem ou foto ao seu app Android.
- Como mostrar uma imagem no seu app com um elemento
Image
combinável. - Práticas recomendadas sobre o uso de recursos
String
.
O que você vai criar
- Melhorar o app Happy Birthday para incluir uma imagem.
Pré-requisitos
- Um computador com o Android Studio instalado.
- O app do codelab Criar um app simples com elementos de texto de composição.
2. Configurar o app
No Android Studio, abra seu projeto Happy Birthday do codelab anterior.
Quando o app for executado, ele vai ficar como o mostrado nesta captura de tela.
Adicionar uma imagem ao projeto
Nesta tarefa, você vai fazer o download de uma imagem da Internet e a adicionar ao app Happy Birthday.
- Abra a imagem do seu app de cartão de aniversário usando este link.
- Clique em Fazer o download.
- Clique na imagem com o botão direito do mouse e salve o arquivo no computador como
androidparty.png
. - Anote onde você salvou a imagem.
Por exemplo, você pode ter usado a pasta Downloads.
- No Android Studio, clique em View > Tool Windows > Resource Manager ou na guia Resource Manager ao lado da janela Project.
- Clique em + (Add resources to the module) > Import Drawables.
- No navegador de arquivos, selecione o arquivo de imagem que você baixou e clique em Open.
Essa ação abre a caixa de diálogo Import drawables.
- O Android Studio vai mostrar uma prévia da imagem. Selecione Density na lista suspensa QUALIFIER TYPE. Você vai descobrir por que está fazendo isso em uma sessão futura.
- Selecione No Density na lista VALUE.
Os dispositivos Android têm telas de tamanhos variados (por exemplo, smartphones, tablets, TVs etc.), e elas também têm diferentes tamanhos de pixel. Ou seja, enquanto um dispositivo tem 160 pixels por polegada quadrada, outro encaixa 480 pixels no mesmo espaço. Caso você não considere essas variações em densidade de pixel, o sistema pode dimensionar suas imagens, resultando em imagens desfocadas, imagens grandes que consomem muita memória ou imagens com tamanho incorreto.
Quando você redimensiona imagens que ultrapassam o tamanho que o sistema Android consegue processar, é gerado um erro de falta de memória. As fotografias e imagens de plano de fundo, como a atual (androidparty.png
), precisam ser colocadas na pasta drawable-nodpi
, o que interrompe o comportamento de redimensionamento.
Para ver mais informações sobre densidades de pixel, consulte Suporte a densidades de pixel diferentes.
- Clique em Próximo.
- O Android Studio mostra a estrutura de pastas em que a imagem será colocada. Observe a pasta
drawable-nodpi
. - Clique em Import(C).
O Android Studio cria uma pasta drawable-nodpi
e coloca a imagem nela. Na visualização de projeto do Android Studio, o nome do recurso é mostrado como androidparty.png (nodpi)
. No sistema de arquivos do computador, o Android Studio criaria uma pasta com o nome drawable-nodpi
.
Caso a imagem seja importada corretamente, ela será adicionada pelo Android Studio à lista na guia Drawable. Essa lista inclui todos os ícones e imagens do app, então você já pode usar a imagem importada.
- Volte à visualização do projeto, clique em View > Tool Windows > Project ou clique na guia Project à esquerda.
- Clique em app > res > drawable para confirmar que a imagem está na pasta
drawable
.
3. Adicionar uma imagem que pode ser composta
Para que uma imagem seja mostrada no app, é necessário informar o local de exibição. Do mesmo modo como você usa um elemento combinável Text
para mostrar texto, é possível usar um elemento Image
para mostrar uma imagem.
Nesta tarefa, você vai adicionar um elemento combinável Image
ao app, usar a imagem que foi transferida por download, posicionar essa imagem e ajustar o tamanho dela para preencher a tela.
Incluir uma função combinável para adicionar uma imagem
- No arquivo
MainActivity.kt
, adicione uma função combinávelGreetingImage()
após a funçãoGreetingText()
. - Transmita dois parâmetros
String
à funçãoGreetingImage()
: um com o nomemessage
para a mensagem de aniversário e outro com o nomefrom
para sua assinatura.
@Composable
fun GreetingImage(message: String, from: String) {
}
- Todas as funções combináveis precisam aceitar um parâmetro
Modifier
opcional. Os modificadores informam para um elemento da interface como serão dispostos, exibidos ou se comportarão no layout pai. Adicione outro parâmetro ao elemento combinávelGreetingImage()
.
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
}
Recursos no Jetpack Compose
Os recursos são os arquivos complementares e o conteúdo estático usados pelo seu código, como bitmaps, strings da interface do usuário, instruções de animação, entre outros. Para saber mais sobre recursos no Android, consulte Visão geral dos recursos de app.
É importante sempre separar do código os recursos do app, como imagens e strings, para que eles possam ser mantidos de forma independente. No momento da execução, o Android usa o recurso adequado com base na configuração atual. Por exemplo, você pode querer fornecer um layout de IU diferente de acordo com o tamanho da tela, ou strings diferentes de acordo com a configuração de idioma.
Como agrupar recursos
Coloque cada tipo de recurso em um subdiretório específico do diretório res/
do seu projeto. Por exemplo, abaixo mostramos a hierarquia de arquivos para um projeto simples:
MyProject/
src/
MyActivity.kt
res/
drawable/
graphic.png
mipmap/
icon.png
values/
strings.xml
Como você pode ver nesse exemplo, o diretório res/
contém todos os recursos em subdiretórios, incluindo um diretório drawable/
para um recurso de imagem, um mipmap/
para ícones na tela de início e um values/
para recursos de string. Se quiser saber mais sobre o uso, o formato e a sintaxe dos recursos do app, consulte a Visão geral dos tipos de recurso.
Como acessar recursos
O Jetpack Compose pode acessar os recursos definidos no seu projeto Android. O acesso pode ser feito usando IDs de recurso que são gerados na classe R
do projeto.
A classe R
é gerada automaticamente pelo Android e contém os IDs de todos os recursos no projeto. Na maioria dos casos, o ID do recurso é igual ao nome do arquivo. Por exemplo, a imagem na hierarquia de arquivos anterior pode ser acessada com este código:
R.drawable.graphic
Na próxima tarefa, você vai usar o arquivo de imagem androidparty.png
, que foi adicionado na tarefa anterior.
- Na função
GreetingImage()
, declare uma propriedadeval
e a nomeie comoimage
. - Faça uma chamada para a função
painterResource()
transmitindo o recursoandroidparty
. Atribua o valor retornado à variávelimage
.
val image = painterResource(R.drawable.androidparty)
O Android Studio destaca o código painterResource
porque é necessário importar a função para compilar o app.
- Clique em
.painterResource
, que é destacado pelo Android Studio. - Clique em Import no pop-up para adicionar a importação de
androidx.compose.ui.res.painterResource
.
A função painterResource()
carrega um recurso de imagem drawable e usa o ID do recurso (R.drawable.androidparty
, neste caso) como um argumento.
- Após a chamada para a função
painterResource()
, adicione um elementoImage
combinável e, em seguida, transmita o combinávelimage
para opainter
como um argumento nomeado.
Image(
painter = image
)
O Android Studio destaca o código Image
porque é necessário importar a função para compilar o app.
Para corrigir esse aviso, adicione a importação abaixo na parte de cima do arquivo MainActivity.kt
:
import androidx.compose.foundation.Image
O aviso inicial foi resolvido, mas se você passar o cursor sobre a palavra Image
, o Android Studio vai mostrar um novo aviso informando que nenhuma destas funções pode ser chamada com os argumentos fornecidos. Isso ocorre porque o argumento fornecido não corresponde a nenhuma das assinaturas da função Image
.
Esse aviso será corrigido na próxima seção.
Conferir a acessibilidade do app
Ao seguir as práticas de programação para acessibilidade, você permite que todos os seus usuários, incluindo aqueles com deficiências, naveguem com mais facilidade no seu app e interajam com ele.
O Android Studio apresenta dicas e alertas para ajudar você a tornar seu app mais acessível. O uso de uma descrição de conteúdo define a finalidade de um elemento da IU, o que faz com que seu app seja mais utilizável com o TalkBack.
Contudo, a imagem neste app só foi incluída para fins decorativos. A adição de uma descrição de conteúdo da imagem dificultaria o uso com o TalkBack neste caso específico. Em vez de definir a descrição de conteúdo que é anunciada ao usuário, você pode definir o argumento contentDescription
da imagem como null
para que o TalkBack ignore o elemento Image
.
- No elemento
Image
, adicione outro argumento nomeado, ocontentDescription
, e defina o valor dele comonull
.
Image(
painter = image,
contentDescription = null
)
Visualizar o elemento Image
combinável
Nesta tarefa, você vai visualizar a imagem combinável e executar o app em um emulador ou dispositivo.
- Na função
BirthdayCardPreview()
, substitua a chamada de funçãoGreetingText()
por uma chamadaGreetingImage()
.
A função vai ser semelhante a este snippet de código:
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
GreetingImage(
message = "Happy Birthday Sam!",
from = "From Emma"
)
}
}
- O painel Design será atualizado automaticamente. Caso contrário, clique em para criar.
Não é mais possível encontrar o texto, porque a nova função tem apenas um elemento Image
, mas não tem um Text
.
4. Adicionar modelo de caixa
Os três elementos básicos de layout padrão do Compose são Column
, Row
e Box
. Você aprendeu sobre os combináveis Column
e Row
nos codelabs anteriores. Agora, vamos conhecer melhor o elemento combinável Box
.
O layout Box
é um dos elementos de layout padrão do Compose. Use o layout Box
para empilhar elementos uns sobre os outros. O layout Box
também permite que você configure o alinhamento específico dos elementos que ele contém.
- Na função
GreetingImage()
, adicione um elementoBox
ao redor do elementoImage
, conforme mostrado abaixo:
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
val image = painterResource(R.drawable.androidparty)
Box {
Image(
painter = image,
contentDescription = null
)
}
}
- Importe a função
androidx.compose.foundation.layout.Box
quando solicitado pelo Android Studio. - Adicione o código para transmitir o parâmetro
modifier
ao elemento combinávelBox
.
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
val image = painterResource(R.drawable.androidparty)
Box(modifier) {
Image(
painter = image,
contentDescription = null
)
}
}
- Ao final do elemento combinável
Box
, chame a funçãoGreetingText()
e transmita a ela a mensagem de aniversário, a assinatura e o modificador, conforme mostrado abaixo:
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
val image = painterResource(R.drawable.androidparty)
Box(modifier) {
Image(
painter = image,
contentDescription = null
)
GreetingText(
message = message,
from = from,
modifier = Modifier
.fillMaxSize()
.padding(8.dp)
)
}
}
- Observe a prévia atualizada no painel Design.
O texto e a imagem vão aparecer.
- Para que as mudanças acima sejam aplicadas no emulador ou em um dispositivo, na função
onCreate()
, substitua a chamada de funçãoGreetingText()
porGreetingImage()
.
O bloco setContent
será semelhante a este snippet de código:
setContent {
HappyBirthdayTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
GreetingImage(
message = "Happy Birthday Sam!",
from = "From Emma"
)
}
}
}
A imagem tem a mesma largura da tela, mas está fixada na parte de cima. Há um espaço em branco na parte de baixo da tela, o que não é muito interessante. Na próxima tarefa, você vai preencher a largura e altura da tela e dimensionar a imagem.
5. Mudar a opacidade e dimensionar a imagem
Nesta tarefa, você vai colocar a imagem em tela cheia para deixar seu app mais bonito. Para fazer isso, use os parâmetros ContentScale
.
Dimensionar conteúdo
Você adicionou a imagem ao seu app e a posicionou. Agora, é necessário ajustar o tipo de escala da imagem, que informa como dimensionar para que ela seja mostrada em tela cheia.
Há alguns tipos de ContentScale
disponíveis. Use o escalonamento de parâmetros ContentScale.Crop
, que dimensiona a imagem de maneira uniforme para manter a proporção de modo que a largura e a altura dela sejam iguais ou maiores que a dimensão correspondente da tela.
- Adicione um argumento nomeado
ContentScale
à imagem.
Image(
painter = image,
contentDescription = null,
contentScale = ContentScale.Crop
)
- Importe a propriedade
androidx.compose.ui.layout.ContentScale
quando solicitado pelo Android Studio. - Confira o painel Design.
A imagem agora preenche toda a tela de prévia, como mostra esta captura de tela:
Mudar a opacidade
Para melhorar o contraste do app, mude a opacidade da imagem de plano de fundo.
Adicione o parâmetro alpha
ao elemento combinável Image
e defina-o como 0.5F
.
Image(
painter = image,
contentDescription = null,
contentScale = ContentScale.Crop,
alpha = 0.5F
)
Observe a mudança na opacidade da imagem.
É bastante código. Está na hora de conferir o resultado de todo o seu trabalho.
Executar o app
Execute o app em um dispositivo ou emulador.
Bom trabalho com a imagem em tela cheia e a mensagem de texto! Você também mudou a opacidade da imagem.
Modificadores de layout
Os modificadores são usados para decorar ou adicionar comportamentos aos elementos da interface do Jetpack Compose. Por exemplo, você pode adicionar planos de fundo, padding ou comportamento a linhas, textos ou botões. Para fazer a configuração deles, um elemento combinável ou layout precisa aceitar um modificador como parâmetro.
Em um codelab anterior, você aprendeu sobre os modificadores e usou o de padding (Modifier.padding
) para adicionar espaço ao redor do elemento combinável Text
. Os modificadores podem ajudar muito, e você verá isso neste e nos próximos programas de aprendizagem.
Por exemplo, o elemento combinável Text
tem um argumento Modifier
que muda a cor do plano de fundo para verde.
// Example
Text(
text = "Hello, World!",
// Solid element background color
modifier = Modifier.background(color = Color.Green)
)
Assim como no exemplo acima, você pode adicionar modificadores a layouts para posicionar os elementos filhos usando propriedades de organização e alinhamento.
Para definir a posição dos filhos em uma Row
, defina os argumentos horizontalArrangement
e verticalAlignment
. Para uma Column
, defina os argumentos verticalArrangement
e horizontalAlignment
.
A propriedade de organização é usada para dispor os elementos filhos quando o tamanho do layout é maior que a soma dos filhos.
Por exemplo: quando o tamanho da Column
é maior que a soma dos tamanhos dos filhos, uma verticalArrangement
pode ser especificada para definir o posicionamento do elementos filhos na Column
. Veja abaixo uma ilustração dos diferentes arranjos verticais:
Da mesma forma, quando o tamanho da Row
é maior que a soma dos tamanhos dos filhos, uma horizontalArrangement
pode ser especificada para definir o posicionamento dos filhos dentro da Row
. Verifique abaixo uma ilustração das diferentes organizações horizontais:
A propriedade de alinhamento é usada para alinhar os elementos filhos no início, no centro ou no fim do layout.
6. Alinhar e organizar o texto
Nesta tarefa, você vai observar o código adicionado no codelab anterior para organizar o texto no app.
- No arquivo
MainActivity.kt
, role até a funçãoGreetingText()
. A propriedadeverticalArrangement
na coluna é definida comoArrangement.Center
. O conteúdo do texto será centralizado na tela.
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Column(
verticalArrangement = Arrangement.Center,
modifier = modifier
) {
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp,
textAlign = TextAlign.Center
)
Text(
text = from,
fontSize = 36.sp,
modifier = Modifier
.padding(16.dp)
.align(alignment = Alignment.End)
)
}
}
Padding
Um elemento da IU envolve o conteúdo. Para evitar que eles fiquem muito próximos, você pode especificar a quantidade de padding em cada lado.
Um padding é usado como um modificador, o que significa que ele pode ser aplicado a qualquer elemento combinável. Para cada lado do elemento, o modificador padding
usa um argumento opcional que define a quantidade de padding.
// This is an example.
Modifier.padding(
start = 16.dp,
top = 16.dp,
end = 16.dp,
bottom = 16.dp
)
- Sua vez No arquivo
MainActivity.kt
, role até onde a funçãoGreetingText()
é chamada e observe o atributo de padding.
modifier = Modifier
.fillMaxSize()
.padding(8.dp)
- Da mesma forma, observe dentro da função
GreetingText()
, o padding do elemento combinávelText
da assinatura.
modifier = Modifier
.padding(16.dp)
.align(alignment = Alignment.End)
7. Adotar boas práticas de código
Tradução
Ao criar apps, é importante lembrar que eles podem ser traduzidos para outro idioma em algum momento. Como você aprendeu em um codelab anterior, um tipo de dado String
é uma sequência de caracteres, como "Happy Birthday Sam!"
.
As strings fixadas no código são escritas diretamente no código do seu app. Elas dificultam a tradução do app para outros idiomas e fazem com que seja mais difícil reutilizar strings em locais diferentes do app. Para resolver esses problemas, você pode extrair strings para um arquivo de recursos. Em vez de fixar strings no código, coloque em um arquivo, nomeie os recursos de string e utilize os nomes sempre que quiser usar as strings. O nome vai continuar igual, mesmo que a string mude ou seja traduzida para outro idioma.
- No arquivo
MainActivity.kt
, role até a funçãoonCreate()
. Selecione a mensagem de aniversário, stringHappy Birthday Sam!
sem aspas. - Clique na lâmpada no lado esquerdo da tela.
- Selecione Extract string resource.
O Android Studio vai abrir a caixa de diálogo Extract Resource. Nela, é possível personalizar o nome do recurso de string e alguns detalhes de armazenamento. O campo Resource name é onde você digita o nome da string que será chamada. O campo Resource value é onde você insere a string.
- Na caixa de diálogo Extract Resource, mude Resource name para
happy_birthday_text
.
Os recursos de string precisam ter nomes em letras minúsculas, e palavras diferentes precisam ser separadas por um sublinhado. Não mude as outras configurações.
- Clique em OK.
- Confira as mudanças no código.
A string fixada no código foi substituída por uma chamada para a função getString()
.
GreetingImage(
message = getString(R.string.happy_birthday_text),
from = "From Emma",
modifier = Modifier.padding(8.dp)
)
- No painel Project, abra o arquivo strings.xml no caminho
app > res > values > strings.xml
e observe que o Android Studio criou um recurso de string com o nomehappy_birthday_text
.
<resources>
<string name="app_name">Happy Birthday</string>
<string name="happy_birthday_text">Happy Birthday Sam!</string>
</resources>
O arquivo strings.xml
tem uma lista de strings que aparecem para o usuário no app. Observe que o nome do app também é um recurso de string. Colocar todas as strings em um só lugar facilita a tradução de todo o texto e a reutilização de uma string em diferentes partes do app.
- Siga as mesmas etapas para extrair o texto do elemento
Text
da assinatura, mas desta vez, insirasignature_text
no campo Resource name.
O arquivo final será semelhante a este snippet de código:
<resources>
<string name="app_name">Happy Birthday</string>
<string name="happy_birthday_text">Happy Birthday Sam!</string>
<string name="signature_text">From Emma</string>
</resources>
- Atualize o
BirthdayCardPreview()
para usarstringResource()
e as strings extraídas.
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
GreetingImage(
message = stringResource(R.string.happy_birthday_text),
from = stringResource(R.string.signature_text)
)
}
}
- Execute o app novamente para conferir se ele ainda funciona.
8. Desafio
Você fez um bom trabalho adicionando a imagem ao seu app. Aqui está um desafio:
- Organize ou alinhe o elemento combinável de texto de assinatura para que ele fique centralizado na tela.
O teste vai ficar assim:
Para sua referência, este é o código da solução para a função GreetingText()
:
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Column(
verticalArrangement = Arrangement.Center,
modifier = modifier
) {
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp,
textAlign = TextAlign.Center
)
Text(
text = from,
fontSize = 36.sp,
modifier = Modifier
.padding(16.dp)
.align(alignment = Alignment.CenterHorizontally)
)
}
}
9. Acessar o código da solução
O código da solução para o app Happy Birthday está no GitHub.
O GitHub é um serviço que possibilita que desenvolvedores gerenciem códigos de projetos de software. Ele usa o Git, um sistema de controle de versões que monitora as mudanças feitas em cada versão do código. Se você já viu o histórico de versões de um arquivo no Documentos Google, pode ver as edições e quando elas foram feitas. Da mesma forma, é possível acompanhar o histórico de versões do código em um projeto. Isso é útil quando você trabalha em um projeto individualmente ou com uma equipe.
O GitHub também tem um site em que é possível ver e gerenciar o projeto. Esse link permite procurar os arquivos do projeto Happy Birthday on-line ou fazer o download deles no seu computador.
Para fazer o download do código do codelab concluído, use este comando git:
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-birthday-card-app.git
Se preferir, você pode baixar o repositório como um arquivo ZIP, descompactar e abrir no Android Studio.
Se você quiser conferir o código da solução, acesse o GitHub (link em inglês).
Ramificações no GitHub
Antes de entender o que é uma ramificação, entenda o que é um repositório. Esse termo se refere a todo o seu projeto (diretórios e arquivos) que você clona (copia) no computador. Uma ramificação é uma versão do seu repositório, ou seja, uma linha de desenvolvimento independente. Neste curso, por exemplo, a ramificação starter pode ser uma versão do seu projeto que você usou para iniciar a criação durante o codelab. A ramificação main ou solution é a versão do seu projeto ao final do codelab, contendo o código completo da solução.
Um repositório pode conter várias ramificações, o que significa que há várias versões do código nele.
10. Conclusão
Você adicionou uma imagem ao seu app Happy Birthday, alinhou o texto aos modificadores, seguiu as diretrizes de acessibilidade e facilitou a tradução para outros idiomas. E o mais importante: você terminou de criar seu app Happy Birthday. Compartilhe seu trabalho nas mídias sociais e use a hashtag #AndroidBasics para que possamos conferir o que você fez.
Resumo
- A guia Resource Manager no Android Studio ajuda você a adicionar e organizar suas imagens e outros recursos.
- Um elemento
Image
combinável é um elemento de IU que mostra imagens no app. - Um elemento
Image
combinável precisa ter uma descrição de conteúdo para deixar seu app mais acessível. - O texto que é mostrado ao usuário, como a mensagem de aniversário, precisa ser extraído para um recurso de string de modo a facilitar a tradução do app para outros idiomas.