---
title: "Layouts com Jetpack Compose Tutorial em Português — Passo a Passo | Kotlin Brasil"
url: "https://kotlin.dev.br/tutoriais/jetpack-compose-layouts/"
markdown_url: "https://kotlin.dev.br/tutoriais/jetpack-compose-layouts.MD"
description: "Aprenda layouts no Jetpack Compose: Row, Column, Box, LazyColumn, Scaffold, Modifier e layouts responsivos. Tutorial completo em português."
date: "2026-03-17"
author: "Karina Melo"
---

# Layouts com Jetpack Compose Tutorial em Português — Passo a Passo | Kotlin Brasil

Aprenda layouts no Jetpack Compose: Row, Column, Box, LazyColumn, Scaffold, Modifier e layouts responsivos. Tutorial completo em português.


Neste tutorial, você vai aprender a construir **layouts com Jetpack Compose**, a toolkit declarativa do Android para construcao de interfaces. Vamos explorar os composables fundamentais — Row, Column, Box — além de listas com LazyColumn, estruturas de tela com Scaffold é o poderoso sistema de [Modifier](/glossario/modifier/). Se você já deu os primeiros passos com Compose no tutorial de [Jetpack Compose básico](/tutoriais/jetpack-compose-básico/), este guia vai expandir bastante o seu repertorio.

## A Filosofia de Layouts no Compose

Diferente do sistema de Views clássico do Android, onde layouts são definidos em XML, no Compose tudo e feito em Kotlin. Cada elemento de interface é uma função [Composable](/glossario/composable/) que descreve o que deve aparecer na tela. Nao existe mais `LinearLayout`, `RelativeLayout` ou `ConstraintLayout` em XML — agora você compoe a interface empilhando funções.

Essa mudanca traz uma vantagem enorme: o layout é o comportamento vivem no mesmo lugar, facilitando a leitura é a manutenção do código.

## Column: Organizando Elementos na Vertical

O `Column` é o equivalente ao antigo `LinearLayout` com orientacao vertical. Ele empilha seus filhos de cima para baixo.

```kotlin
@Composable
fun CartaoUsuario() {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        Text(
            text = "Maria Silva",
            style = MaterialTheme.typography.headlineSmall
        )
        Text(
            text = "Desenvolvedora Android",
            style = MaterialTheme.typography.bodyMedium
        )
        Text(
            text = "São Paulo, Brasil",
            style = MaterialTheme.typography.bodySmall
        )
    }
}
```

O parametro `verticalArrangement` controla como o espaco e distribuído entre os filhos. As opções mais comuns são `Arrangement.Top`, `Arrangement.Center`, `Arrangement.SpaceBetween`, `Arrangement.SpaceEvenly` e `Arrangement.spacedBy()`.

Para alinhar os filhos horizontalmente dentro de um `Column`, use o parametro `horizontalAlignment`:

```kotlin
Column(
    modifier = Modifier.fillMaxWidth(),
    horizontalAlignment = Alignment.CenterHorizontally
) {
    Text("Texto centralizado")
    Button(onClick = { }) {
        Text("Botao centralizado")
    }
}
```

## Row: Organizando Elementos na Horizontal

O `Row` funciona da mesma forma que o `Column`, mas na horizontal — os filhos são posicionados da esquerda para a direita.

```kotlin
@Composable
fun BarraDeAcoes() {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 16.dp),
        horizontalArrangement = Arrangement.SpaceBetween,
        verticalAlignment = Alignment.CenterVertically
    ) {
        IconButton(onClick = { }) {
            Icon(Icons.Default.ArrowBack, contentDescription = "Voltar")
        }
        Text(
            text = "Detalhes",
            style = MaterialTheme.typography.titleMedium
        )
        IconButton(onClick = { }) {
            Icon(Icons.Default.MoreVert, contentDescription = "Mais opções")
        }
    }
}
```

Um recurso muito útil dentro de `Row` e o `Modifier.weight()`, que distribui o espaco disponivel proporcionalmente, semelhante ao `layout_weight` do antigo LinearLayout:

```kotlin
Row(modifier = Modifier.fillMaxWidth()) {
    Text(
        text = "Nome do produto",
        modifier = Modifier.weight(1f)
    )
    Text(
        text = "R$ 49,90",
        modifier = Modifier.width(100.dp),
        textAlign = TextAlign.End
    )
}
```

Aqui, o nome do produto ocupa todo o espaco restante enquanto o preco mantém uma largura fixa.

## Box: Sobreposicao de Elementos

O `Box` permite empilhar elementos um sobre o outro, como camadas. E o equivalente ao `FrameLayout` do sistema clássico.

```kotlin
@Composable
fun ImagemComBadge() {
    Box(
        modifier = Modifier.size(120.dp)
    ) {
        Image(
            painter = painterResource(id = R.drawable.foto_perfil),
            contentDescription = "Foto de perfil",
            modifier = Modifier.fillMaxSize(),
            contentScale = ContentScale.Crop
        )
        Badge(
            modifier = Modifier.align(Alignment.BottomEnd)
        ) {
            Text("3")
        }
    }
}
```

O parametro `contentAlignment` do `Box` define o alinhamento padrão dos filhos, enquanto `Modifier.align()` permite posicionar cada filho individualmente.

## O Sistema de Modifier

O [Modifier](/glossario/modifier/) e provavelmente o conceito mais importante de todo o Jetpack Compose. Ele e uma cadeia de decoracoes que você aplica a qualquer composable para controlar tamanho, padding, alinhamento, cliques, cor de fundo e muito mais.

```kotlin
Text(
    text = "Elemento estilizado",
    modifier = Modifier
        .fillMaxWidth()
        .padding(16.dp)
        .background(
            color = MaterialTheme.colorScheme.primaryContainer,
            shape = RoundedCornerShape(8.dp)
        )
        .padding(12.dp)
        .clickable { /* acao ao clicar */ }
)
```

A **ordem dos modifiers importa**. No exemplo acima, o primeiro `padding` cria espaco externo (como margin), o `background` aplica a cor, e o segundo `padding` cria espaco interno entre o fundo e o texto. Inverter a ordem muda completamente o resultado visual.

Alguns dos modifiers mais usados no dia a dia:

- `fillMaxWidth()` / `fillMaxHeight()` / `fillMaxSize()` — preencher o espaco disponivel
- `width()` / `height()` / `size()` — dimensoes fixas
- `padding()` — espacamento interno ou externo (depende da ordem)
- `background()` — cor ou forma de fundo
- `clip()` — recortar o conteudo com uma forma
- `border()` — adicionar borda
- `clickable {}` — tornar o elemento clicavel
- `weight()` — distribuir espaco dentro de Row ou Column

## LazyColumn e LazyRow: Listas Eficientes

Para listas longas, usar `Column` com muitos itens seria um desastre de performance, porque todos os itens seriam compostos de uma vez. E ai que entram `LazyColumn` e `LazyRow`, equivalentes ao RecyclerView do sistema clássico. Eles só compoem os itens que estao visiveis na tela.

```kotlin
@Composable
fun ListaDeProdutos(produtos: List<Produto>) {
    LazyColumn(
        modifier = Modifier.fillMaxSize(),
        contentPadding = PaddingValues(16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        items(
            items = produtos,
            key = { it.id }
        ) { produto ->
            CartaoProduto(produto)
        }
    }
}

@Composable
fun CartaoProduto(produto: Produto) {
    Card(
        modifier = Modifier.fillMaxWidth()
    ) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text(
                text = produto.nome,
                style = MaterialTheme.typography.titleMedium
            )
            Text(
                text = "R$ ${"%.2f".format(produto.preco)}",
                style = MaterialTheme.typography.bodyLarge
            )
        }
    }
}
```

O parametro `key` e muito importante: ele permite que o Compose identifique cada item unicamente, otimizando recomposicoes quando a lista muda.

Para listas horizontais, basta trocar para `LazyRow`:

```kotlin
LazyRow(
    contentPadding = PaddingValues(horizontal = 16.dp),
    horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
    items(categorias) { categoria ->
        ChipCategoria(categoria)
    }
}
```

Se você já usou [RecyclerView](/tutoriais/kotlin-recyclerview-tutorial/), vai notar que o código com LazyColumn e significativamente mais simples — não há necessidade de Adapter, ViewHolder ou layout XML separado.

## Scaffold: Estrutura de Tela Completa

O `Scaffold` e um composable que fornece a estrutura básica de uma tela Material Design, incluindo slots para TopAppBar, BottomBar, FloatingActionButton e conteudo principal.

```kotlin
@Composable
fun TelaPrincipal() {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("Meu Aplicativo") },
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.primary,
                    titleContentColor = MaterialTheme.colorScheme.onPrimary
                )
            )
        },
        floatingActionButton = {
            FloatingActionButton(onClick = { }) {
                Icon(Icons.Default.Add, contentDescription = "Adicionar")
            }
        },
        bottomBar = {
            NavigationBar {
                NavigationBarItem(
                    selected = true,
                    onClick = { },
                    icon = { Icon(Icons.Default.Home, contentDescription = "Inicio") },
                    label = { Text("Inicio") }
                )
                NavigationBarItem(
                    selected = false,
                    onClick = { },
                    icon = { Icon(Icons.Default.Settings, contentDescription = "Config") },
                    label = { Text("Config") }
                )
            }
        }
    ) { paddingValues ->
        LazyColumn(
            modifier = Modifier.padding(paddingValues)
        ) {
            items(50) { indice ->
                Text(
                    text = "Item $indice",
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(16.dp)
                )
            }
        }
    }
}
```

Repare no parametro `paddingValues` que o Scaffold passa para o conteudo. Ele inclui o espaco ocupado pela TopAppBar e pela BottomBar, garantindo que o conteudo não fique escondido atras deles. Sempre aplique esse padding ao conteudo principal.

## ConstraintLayout no Compose

Para layouts mais complexos onde os elementos precisam se posicionar em relação uns aos outros, o Compose oferece o `ConstraintLayout`. Ele exige uma dependência adicional:

```kotlin
// build.gradle.kts
implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0")
```

```kotlin
@Composable
fun PerfilUsuario() {
    ConstraintLayout(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
    ) {
        val (foto, nome, cargo) = createRefs()

        Image(
            painter = painterResource(id = R.drawable.avatar),
            contentDescription = "Avatar",
            modifier = Modifier
                .size(64.dp)
                .clip(CircleShape)
                .constrainAs(foto) {
                    start.linkTo(parent.start)
                    top.linkTo(parent.top)
                }
        )

        Text(
            text = "Ana Costa",
            style = MaterialTheme.typography.titleMedium,
            modifier = Modifier.constrainAs(nome) {
                start.linkTo(foto.end, margin = 12.dp)
                top.linkTo(foto.top)
            }
        )

        Text(
            text = "Engenheira de Software",
            style = MaterialTheme.typography.bodyMedium,
            modifier = Modifier.constrainAs(cargo) {
                start.linkTo(nome.start)
                top.linkTo(nome.bottom, margin = 4.dp)
            }
        )
    }
}
```

Embora o ConstraintLayout esteja disponivel, na prática a maioria dos layouts no Compose pode ser resolvida combinando Row, Column e Box. Reserve o ConstraintLayout para casos onde as relacoes entre elementos são realmente complexas.

## Layouts Responsivos

Para criar layouts que se adaptam a diferentes tamanhos de tela — celulares, tablets, desktops — você pode usar `BoxWithConstraints`, que fornece as dimensoes disponiveis:

```kotlin
@Composable
fun LayoutAdaptavel() {
    BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
        if (maxWidth > 600.dp) {
            // Layout para telas grandes: duas colunas
            Row(modifier = Modifier.fillMaxSize()) {
                ListaDeProdutos(
                    produtos = produtos,
                    modifier = Modifier.weight(1f)
                )
                DetalhesProduto(
                    produto = produtoSelecionado,
                    modifier = Modifier.weight(1f)
                )
            }
        } else {
            // Layout para telas pequenas: coluna unica
            ListaDeProdutos(
                produtos = produtos,
                modifier = Modifier.fillMaxSize()
            )
        }
    }
}
```

Essa abordagem e fundamental para apps que rodam em dispositivos com tamanhos de tela variados, especialmente com o crescimento do Kotlin Multiplatform e do Compose Multiplatform.

## Conclusão

Dominar layouts no Jetpack Compose e questao de entender bem tres coisas: os composables de posicionamento (Column, Row, Box), o sistema de Modifier e os componentes de listas lazy. Com essas ferramentas, você consegue construir praticamente qualquer interface. O Scaffold organiza a estrutura geral da tela, e para casos excepcionais o ConstraintLayout esta a disposicao.

A melhor forma de fixar esses conceitos e colocando a mao na massa. Pegue um design qualquer — pode ser uma tela do seu app favorito — e tente reproduzi-lo usando apenas Compose. Você vai perceber que a combinacao de [funções](/tutoriais/funções-kotlin/), [lambdas](/tutoriais/lambdas-kotlin/) e composables torna o processo muito mais fluido do que o antigo sistema de Views em XML.
