Criar um app simples com elementos de texto combináveis

1. Antes de começar

Neste codelab, você vai usar o Jetpack Compose para criar um app Android simples que mostra uma mensagem de aniversário na tela.

Pré-requisitos

  • Como criar um app no Android Studio.
  • Como executar um app em um emulador ou dispositivo Android.

O que você vai aprender

  • Como escrever funções combináveis, como Text, Column e Row.
  • Como mostrar texto no app em um layout.
  • Como formatar o texto, por exemplo, mudando o tamanho dele.

O que você vai criar

  • Um app Android que mostra uma mensagem de aniversário em formato de texto. No final, ela vai ficar assim:

2ff181d48325023c.png

O que é necessário

  • Um computador com o Android Studio instalado.

2. Configurar um app Happy Birthday

Nesta tarefa, você vai configurar um projeto no Android Studio com um modelo Empty Activity e mudar a mensagem de texto para uma mensagem de aniversário personalizada.

Criar um projeto Empty Activity

  1. Na caixa de diálogo Welcome to Android Studio, selecione New Project.
  2. Na caixa de diálogo New Project, selecione Empty Activity e clique em Next.
  3. Digite Happy Birthday no campo Name, selecione um nível mínimo de API de 24 (Nougat) no campo Minimum SDK e clique em Finish.

b17b607847b0d0ab.png

  1. Espere o Android Studio criar os arquivos e o projeto.
  2. Clique em fd26b2e3c2870c3.png Run 'app'.

O app vai ficar assim:

d8299bfc1a82cd57.png

Quando você cria o app Happy Birthday com o modelo Empty Activity, o Android Studio configura recursos para um app Android básico, incluindo uma mensagem Hello Android! na tela. Neste codelab, você vai aprender como essa mensagem é mostrada, como mudar o texto dela para uma mensagem de aniversário e como adicionar e formatar outras mensagens.

O que é uma interface do usuário?

A interface do usuário (interface) de um app é o que é mostrado na tela: texto, imagens, botões e muitos outros tipos de elementos, além de como eles são organizados na tela. Essa é a forma como o app mostra informações ao usuário e como o usuário interage com o app.

Esta imagem contém um botão clicável, uma mensagem de texto e um campo de entrada de texto em que os usuários podem inserir dados.

9a2df39af4122803.png

Botão clicável

50a9b402fd9037c0.png

Mensagem de texto em um card

17794ea52cfb5473.png

Campo de entrada de texto

Cada um desses elementos é chamado de componente de interface. Quase tudo o que você vê na tela do app é um elemento da interface (também conhecido como componente da interface). Os elementos podem ser interativos, como um botão clicável ou um campo de entrada editável, ou podem ser imagens decorativas.

Nos apps abaixo, tente encontrar o máximo possível de componentes de interface.

Mostrando apps recomendados

Neste codelab, você vai trabalhar com um elemento da interface que mostra texto, conhecido como elemento Text.

3. O que é o Jetpack Compose?

O Jetpack Compose é um kit de ferramentas moderno para a criação de IUs do Android. O Compose simplifica e acelera o desenvolvimento da interface no Android com menos código, ferramentas com a mais alta tecnologia e recursos Kotlin intuitivos. Com o Compose, você pode criar a interface definindo um conjunto de funções, conhecidas como funções combináveis, que recebem dados e descrevem elementos da interface.

Funções combináveis

As funções combináveis são o elemento básico de uma interface no Compose. Uma função combinável:

  • descreve uma parte da interface;
  • não retorna nada;
  • recebe uma entrada e gera o que será mostrado na tela.

Anotações

Anotações são meios de anexar informações extras ao código. Essas informações ajudam ferramentas como o compilador do Jetpack Compose e outros desenvolvedores a entender o código do app.

Uma anotação é aplicada adicionando o caractere @ como prefixo ao nome dela no início da declaração em questão. Vários elementos de código, como propriedades, funções e classes, podem ser anotados. Mais adiante no curso, você vai aprender sobre classes.

O diagrama abaixo é um exemplo de função com anotação:

Diagrama mostrando a anatomia de uma função combinável, em que o caractere de prefixo de anotação @ é um elemento combinável seguido pela declaração da função.

O snippet de código abaixo tem exemplos de propriedades anotadas. Você vai usar esses recursos nos próximos codelabs.

// Example code, do not copy it over

@Json
val imgSrcUrl: String

@Volatile
private var INSTANCE: AppDatabase? = null

Anotações com parâmetros

Anotações podem usar parâmetros. Elas fornecem mais informações para as ferramentas que fazem o processamento delas. Confira abaixo alguns exemplos de anotação @Preview com e sem parâmetros.

Captura de tela do Android Studio mostrando o código e a prévia

Anotação sem parâmetros

Captura de tela do Android Studio mostrando o código e a prévia

Plano de fundo da prévia da anotação

Captura de tela do Android Studio mostrando o código e a prévia

Anotação com um título de visualização

É possível transmitir vários argumentos para a anotação, conforme mostrado aqui.

895f8d3a229c287a.png

Captura de tela do Android Studio mostrando o código e a prévia

Anotação com título de visualização e interface do sistema (tela do smartphone)

O Jetpack Compose inclui uma ampla variedade de anotações integradas. Você já aprendeu sobre as anotações @Composable e @Preview até agora. Vamos falar mais sobre as anotações e os usos delas mais adiante no curso.

Exemplo de uma função combinável

A função combinável recebe a anotação @Composable. Todas as funções desse tipo precisam ter essa anotação. Ela informa ao compilador do Compose que essa função se destina a converter dados em interface. Vale lembrar que um compilador é um programa especial que pega o código que você escreveu, analisa linha por linha e converte em algo que o computador pode entender (linguagem de máquina).

O snippet de código abaixo é um exemplo de função simples de composição que recebe dados (o parâmetro de função name) e os usa para renderizar um elemento de texto na tela.

@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

Algumas observações sobre a função combinável:

  • O Jetpack Compose foi criado com base em funções combináveis. Essas funções permitem definir a interface do app de maneira programática, descrevendo a aparência dele, em vez de se concentrar no processo de construção da interface. Para criar uma função combinável, basta adicionar a anotação @Composable ao nome da função.
  • As funções combináveis podem aceitar argumentos, que permitem à lógica do app descrever ou modificar a interface. Nesse caso, o elemento da interface aceita uma String para que a mensagem use o nome do usuário.

Observe as funções combináveis no código

  1. No Android Studio, abra o arquivo MainActivity.kt.
  2. Role até a função GreetingPreview(). Essa função combinável ajuda a mostrar uma prévia da função Greeting(). Como prática recomendada, as funções devem sempre ser nomeadas ou renomeadas para descrever a funcionalidade que elas têm. Mude o nome da função para BirthdayCardPreview().
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        Greeting("Android")
    }
}

As funções combináveis podem chamar outras funções desse tipo. Neste snippet de código, a função de visualização está chamando a função combinável Greeting().

Observe que a função anterior também tem outra anotação, @Preview, com um parâmetro antes da anotação @Composable. Você vai saber mais sobre os argumentos transmitidos à anotação @Preview mais adiante no curso.

Nomes de funções combináveis

A função de composição que não retorna nada e carrega a anotação @Composable PRECISA ser nomeada usando o padrão Pascal Case. Ele se refere a uma convenção de nomenclatura em que a primeira letra de cada palavra em uma palavra composta é maiúscula. A diferença entre o padrão Pascal e o padrão de letras concatenadas é que todas as palavras no Pascal têm as iniciais maiúsculas. No padrão de letras concatenadas, a primeira palavra pode estar em maiúscula ou minúscula.

A função Compose:

  • PRECISA ser um substantivo: DoneButton()
  • NÃO pode ser um verbo ou frase verbal: DrawTextField()
  • NÃO pode ser uma preposição nominal: TextFieldWithLink()
  • NÃO pode ser um adjetivo: Bright()
  • NÃO pode ser um advérbio: Outside()
  • Substantivos PODEM ter adjetivos descritivos como prefixos: RoundIcon()

Para saber mais, consulte Como nomear funções combináveis (link em inglês).

Exemplo de código. Não copie

// Do: This function is a descriptive PascalCased noun as a visual UI element
@Composable
fun FancyButton(text: String) {}

// Do: This function is a descriptive PascalCased noun as a non-visual element
// with presence in the composition
@Composable
fun BackButtonHandler() {}

// Don't: This function is a noun but is not PascalCased!
@Composable
fun fancyButton(text: String) {}

// Don't: This function is PascalCased but is not a noun!
@Composable
fun RenderFancyButton(text: String) {}

// Don't: This function is neither PascalCased nor a noun!
@Composable
fun drawProfileImage(image: ImageAsset) {}

4. Painel Design do Android Studio

O Android Studio permite visualizar as funções combináveis no ambiente de desenvolvimento integrado, em vez de instalar o app em um dispositivo ou emulador Android. Como você aprendeu no programa de aprendizagem anterior, é possível conferir uma prévia da aparência do app no painel Design do Android Studio.

2bb27291fa8c8ecc.png

A função combinável precisa fornecer valores padrão para todos os parâmetros para que a prévia possa ser mostrada. Por esse motivo, uma prévia direta da função Greeting() não é recomendada. Em vez disso, é necessário adicionar outra função, a BirthdayCardPreview(), que chama a Greeting() com um parâmetro adequado.

@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        Greeting("Android")
    }
}

Para conferir uma prévia:

  1. Na função BirthdayCardPreview(), substitua o argumento "Android" na Greeting() pelo seu nome.
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        Greeting("James")
    }
}
  1. A prévia será atualizada automaticamente.

A prévia atualizada vai aparecer.

907e7542c84daf9f.png

5. Adicionar um novo elemento de texto

Nesta tarefa, você vai remover a saudação Hello $name! e adicionar uma mensagem de aniversário.

Adicionar uma nova função combinável

  1. No arquivo MainActivity.kt, exclua a definição da função Greeting(). Você vai adicionar sua própria função para mostrar a saudação no codelab mais tarde.

Remova o código abaixo

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello $name!",
        modifier = modifier
    )
}
  1. Dentro da função onCreate(), observe que a chamada da função Greeting() agora está em vermelho. Essa cor indica um erro. Passe o cursor sobre essa chamada de função, e o Android Studio vai mostrar informações sobre o erro.

9634619e59248532.png

  1. Exclua a chamada de função Greeting() com os argumentos das funções onCreate() e BirthdayCardPreview(). Seu arquivo MainActivity.kt vai ficar parecido com este:
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            HappyBirthdayTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                }
            }
        }
    }
}

@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
    }
}
  1. Antes da função BirthdayCardPreview(), adicione uma nova função chamada GreetingText(). Adicione a anotação @Composable antes da função, porque ela será uma função combinável descrevendo um elemento combinável Text.
@Composable
fun GreetingText() {
}
  1. É uma prática recomendada fazer com que a função combinável aceite um parâmetro Modifier e transmita esse modifier para o primeiro filho. Você vai saber mais sobre o Modifier e elementos filhos nas próximas tarefas e codelabs. Por enquanto, adicione um parâmetro Modifier à função GreetingText().
@Composable
fun GreetingText(modifier: Modifier = Modifier) {
}
  1. Adicione um parâmetro message do tipo String à função combinável GreetingText().
@Composable
fun GreetingText(message: String, modifier: Modifier = Modifier) {
}
  1. Na função GreetingText(), adicione uma função combinável Text transmitindo a mensagem de texto como um argumento nomeado.
@Composable
fun GreetingText(message: String, modifier: Modifier = Modifier) {
    Text(
        text = message
    )
}

A função GreetingText() mostra texto na interface. Isso é feito chamando a função combinável Text().

Visualizar a função

Nesta tarefa, você vai visualizar a função GreetingText() no painel Design.

  1. Chame a função GreetingText() dentro da BirthdayCardPreview().
  2. Transmita um argumento String para a função GreetingText(), que é uma mensagem de aniversário para seu amigo. Você pode personalizar a mensagem com o nome que quiser, como "Happy Birthday Sam!".
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        GreetingText(message = "Happy Birthday Sam!")
    }
}
  1. No painel Design, atualizado automaticamente, confira as mudanças que você fez.

334688e2e89fb19e.png

6. Mudar o tamanho da fonte

Você adicionou texto à interface do usuário, mas ele ainda não está com a aparência do app final. Nesta tarefa, você vai aprender a mudar o tamanho e a cor do texto, além de outros atributos que afetam a aparência do elemento de texto. Você também pode testar tamanhos e cores de fonte diferentes.

Pixels escalonáveis

Os pixels escalonáveis (SP, na sigla em inglês) são uma unidade de medida para o tamanho da fonte. Os elementos da interface em apps Android usam duas unidades de medida diferentes: pixels de densidade independente (DP), que será usada depois no layout, e pixels escalonáveis (SP). Por padrão, a unidade SP é do mesmo tamanho que a DP, mas ela é redimensionada com base no tamanho de texto preferencial do usuário nas configurações do smartphone.

  1. No arquivo MainActivity.kt, role até o elemento combinável Text() na função GreetingText().
  2. Transmita um argumento fontSize à função Text() como um segundo argumento nomeado e o defina como um valor de 100.sp.
Text(
    text = message,
    fontSize = 100.sp
)

O Android Studio destaca o código .sp porque é preciso importar algumas classes ou propriedades para compilar o app.

ba6c753d4eefd1d5.png

  1. Clique em .sp, que é destacado pelo Android Studio.
  2. Clique no botão Import no pop-up para importar o androidx.compose.ui.unit.sp e usar a propriedade da extensão .sp.
  1. Role até a parte de cima do arquivo e observe as instruções import, onde você vai encontrar uma instrução import androidx.compose.ui.unit.sp, o que significa que o Android Studio vai adicionar o pacote ao arquivo.

e073e9d3465e080c.png

  1. Observe a prévia atualizada do tamanho da fonte. O motivo da sobreposição da mensagem é que você precisa especificar a altura da linha.

3bf48548c10f4ea.png

  1. Atualize o elemento combinável Text para incluir a altura da linha.
@Composable
fun GreetingText(message: String, modifier: Modifier = Modifier) {
    Text(
        text = message,
        fontSize = 100.sp,
        lineHeight = 116.sp,
    )
}

ef457e9b19d4d495.png

Agora é possível testar diferentes tamanhos de fonte.

7. Adicionar outro elemento de texto

Nas tarefas anteriores, você adicionou uma mensagem de aniversário para seu amigo. Nesta, você vai assinar o cartão com seu nome.

  1. No arquivo MainActivity.kt, role até a função GreetingText().
  2. Transmita à função um parâmetro from do tipo String para sua assinatura.
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier)
  1. Após a mensagem de aniversário Text, adicione outro elemento combinável Text que aceite um argumento text definido como o valor from.
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Text(
        // ...
    )
    Text(
        text = from
    )
}
  1. Adicione um argumento nomeado fontSize definido como um valor de 36.sp.
Text(
    text = from,
    fontSize = 36.sp
)
  1. Role até a função BirthdayCardPreview().
  2. Adicione outro argumento String para assinar o cartão, como "From Emma".
GreetingText(message = "Happy Birthday Sam!", from = "From Emma")
  1. Observe a prévia.

8d148222c669dcad.png

Uma função combinável pode descrever vários elementos da interface. No entanto, se você não oferecer orientações sobre como eles devem ser organizados, o Compose poderá organizar os elementos de uma maneira que você não quer. Por exemplo, o código anterior gera dois elementos de texto que se sobrepõem, porque não há orientação sobre como organizar os dois.

Na próxima tarefa, você vai aprender a organizar os elementos combináveis em uma linha e uma coluna.

8. Organizar os elementos de texto em uma linha e uma coluna

Hierarquia da interface

A hierarquia da interface é baseada em contenção. Isso significa que um componente pode conter um ou mais componentes, e às vezes os termos pai e filho são usados. O contexto é que os elementos pais da interface têm elementos filhos, que por sua vez podem conter outros elementos filhos. Nesta seção, você vai aprender sobre os elementos combináveis Column, Row e Box, que podem atuar como elementos pais da interface.

9270b7e10f954dcb.png

Os três elementos básicos de layout padrão do Compose são Column, Row e Box. Você vai saber mais sobre o elemento combinável Box no próximo codelab.

coluna mostrando três elementos organizados verticalmente e uma linha mostrando três elementos organizados horizontalmente

Column, Row e Box são funções combináveis que usam conteúdo de composição como argumentos para que você possa colocar itens dentro desses elementos de layout. Por exemplo, cada elemento filho dentro de um elemento combinável Row é posicionado horizontalmente um ao lado do outro em uma linha.

// Don't copy.
Row {
    Text("First Column")
    Text("Second Column")
}

Esses elementos de texto são mostrados lado a lado na tela, como visto nesta imagem.

As bordas azuis são apenas para fins demonstrativos e não são mostradas.

7117f9998760a828.png

Sintaxe de lambdas finais

No snippet de código anterior, são usadas chaves, em vez de parênteses, na função combinável Row. Isso é chamado de sintaxe de lambdas finais. Você vai aprender sobre lambdas e sintaxe de lambdas finais em detalhes mais adiante no curso. Por enquanto, conheça esta sintaxe mais usada do Compose.

O Kotlin oferece uma sintaxe especial para transmitir funções como parâmetros para outras funções, quando o último parâmetro também é uma função.

o parâmetro de função é o último parâmetro

Ao transmitir uma função como esse parâmetro, você pode usar a sintaxe de lambdas finais. Em vez de colocar a função entre parênteses, coloque-a fora dos parênteses, entre chaves. Essa é uma prática comum e recomendada no Compose, então você precisa se familiarizar com a aparência do código.

Por exemplo, o último parâmetro na função combinável Row() é o parâmetro content, uma função que descreve os elementos de interface filhos. Suponha que você queira criar uma linha com três elementos de texto. Esse código funcionaria, mas seria muito complicado usar o parâmetro nomeado para a lambda final:

Row(
    content = {
        Text("Some text")
        Text("Some more text")
        Text("Last text")
    }
)

O parâmetro content é o último na assinatura da função, e o valor dele é transmitido como uma expressão lambda. Por enquanto, não tem problema se você não souber o que é uma lambda, apenas conheça a sintaxe. É possível remover o parâmetro content e os parênteses desta maneira:

Row {
    Text("Some text")
    Text("Some more text")
    Text("Last text")
}

Organizar os elementos de texto em uma linha

Nesta tarefa, você organiza os elementos de texto no seu app em uma linha para evitar sobreposição.

  1. No arquivo MainActivity.kt, role até a função GreetingText().
  2. Adicione o elemento combinável Row ao redor dos elementos de texto para que ele mostre uma linha com dois desses elementos. Selecione os dois combináveis Text e clique no ícone de lâmpada. Selecione Surround with widget > Surround with Row.

7ca98d82742d60b9.png

94f248eb6f802b93.png

Agora, a função ficará parecida com este snippet de código:

@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Row {
        Text(
            text = message,
            fontSize = 100.sp,
            lineHeight = 116.sp,
        )
        Text(
            text = from,
            fontSize = 36.sp
        )
    }
}
  1. O Android Studio importa automaticamente a função Row para você. Role até a parte de cima e observe a seção de importação. O import androidx.compose.foundation.layout.Row deve ter sido adicionado.
  2. Observe a prévia atualizada no painel Design. Mude temporariamente o tamanho da fonte da mensagem de aniversário para 30.sp.

A mensagem de aniversário e a assinatura são mostradas lado a lado em uma linha.

A prévia parece muito melhor agora que não há sobreposição. No entanto, não é isso que você quer porque não há espaço suficiente para sua assinatura. Na próxima tarefa, você vai organizar os elementos de texto em uma coluna para resolver esse problema.

Organizar os elementos de texto em uma coluna

Nesta tarefa, é sua vez de mudar a função GreetingText() para organizar os elementos de texto em uma coluna. A prévia vai ficar assim:

d80295e73578e75d.png

Agora que você já tentou fazer isso por conta própria, confira seu código em relação ao da solução neste snippet:

@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column {
        Text(
            text = message,
            fontSize = 100.sp,
            lineHeight = 116.sp,
        )
        Text(
            text = from,
            fontSize = 36.sp
        )
    }
}

Observe o pacote importado automaticamente pelo Android Studio:

import androidx.compose.foundation.layout.Column

Não se esqueça que você precisa transmitir o parâmetro modificador aos elementos filhos dos elementos combináveis. Isso significa que você precisa transmitir o parâmetro ao combinável Column.

@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column(modifier = modifier) {
        Text(
            text = message,
            fontSize = 100.sp,
            lineHeight = 116.sp,
        )
        Text(
            text = from,
            fontSize = 36.sp
        )
    }
}

9. Adicionar a saudação ao app

Quando estiver contente com a prévia, é hora de adicionar o elemento combinável ao app no seu dispositivo ou emulador.

  1. No arquivo MainActivity.kt, role até a função onCreate().
  2. Chame a função GreetingText() do bloco Surface.
  3. Transmita a função GreetingText(), a mensagem de aniversário e a assinatura.

A função onCreate() concluída vai ficar parecida com este snippet de código:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            HappyBirthdayTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    GreetingText(message = "Happy Birthday Sam!", from = "From Emma")
                }
            }
        }
    }
}
  1. Crie e execute o app no emulador.

59e9c0c6e19748ff.png

Centralizar a saudação

  1. Para centralizar a saudação, adicione um parâmetro chamado verticalArrangement e defina-o como Arrangement.Center. Você vai aprender mais sobre o verticalArrangement em um próximo codelab.
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column(
        verticalArrangement = Arrangement.Center,
        modifier = modifier
    ) {
        // ...
    }
}
  1. Adicione o padding 8.dp ao redor da coluna. É recomendável usar valores de padding em incrementos de 4.dp.
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column(
        verticalArrangement = Arrangement.Center,
        modifier = modifier.padding(8.dp)
    ) {
        // ...
    }
}
  1. Para deixar o app ainda mais bonito, centralize o texto da saudação usando textAlign.
Text(
    text = message,
    fontSize = 100.sp,
    lineHeight = 116.sp,
    textAlign = TextAlign.Center
)

28c8e62f86323ba4.png

Na captura de tela acima, somente a saudação está centralizada devido ao parâmetro textAlign. A assinatura, From Emma, tem o alinhamento padrão à esquerda.

  1. Adicione padding à assinatura e alinhe-a à direita.
Text(
    text = from,
    fontSize = 36.sp,
    modifier = Modifier
        .padding(16.dp)
        .align(alignment = Alignment.End)
)

82b858f2f79ca9c4.png

Adotar práticas recomendadas

É recomendável transmitir os atributos de modificador junto ao modificador do elemento combinável pai. Atualize o parâmetro do modificador no GreetingText() da seguinte maneira:

onCreate()

Surface(
    //...
) {
    GreetingText(
        message = "Happy Birthday Sam!",
        from = "From Emma",
        modifier = Modifier.padding(8.dp)
    )
}

GreetingText()

@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column(
        verticalArrangement = Arrangement.Center,
        modifier = modifier
    ) {
        // ...
    }
}

Crie e execute o app no emulador para conferir o resultado final.

2ff181d48325023c.png

10. Acessar o código da solução

O MainActivity.kt concluído:

package com.example.happybirthday

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.happybirthday.ui.theme.HappyBirthdayTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            HappyBirthdayTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    GreetingText(
                        message = "Happy Birthday Sam!",
                        from = "From Emma",
                        modifier = Modifier.padding(8.dp)
                    )
                }
            }
        }
    }
}

@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)
        )
    }
}

@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        GreetingText(message = "Happy Birthday Sam!", from = "From Emma")
    }
}

11. Conclusão

Você criou seu app Happy Birthday.

No próximo codelab, você vai adicionar uma imagem ao app e mudar o alinhamento dos elementos de texto para que fiquem mais bonitos.

Resumo

  • O Jetpack Compose é um kit de ferramentas moderno para criação de interface nativa no Android. Ele simplifica e acelera o desenvolvimento de interfaces no Android com menos código, ferramentas com a mais alta tecnologia e APIs Kotlin intuitivas.
  • A interface do usuário (interface) de um app é o que você vê na tela: texto, imagens, botões e muitos outros tipos de elementos.
  • Funções combináveis são o elemento básico fundamental do Compose. Uma função combinável é uma função que descreve alguma parte da interface.
  • A função combinável recebe a anotação @Composable. Essa anotação informa ao compilador do Compose que essa função se destina a converter dados em interface.
  • Os três elementos básicos de layout padrão do Compose são Column, Row, e Box. Essas são funções combináveis, ou seja, você pode colocar itens nelas. Por exemplo, cada filho em uma Row será colocado horizontalmente um ao lado do outro.

Saiba mais