---
title: "Compose Grid, FlexBox e Media Query: Guia Prático"
url: "https://kotlin.dev.br/blog/jetpack-compose-grid-flexbox-media-query-2026/"
markdown_url: "https://kotlin.dev.br/blog/jetpack-compose-grid-flexbox-media-query-2026.MD"
description: "Domine os novos layouts Grid, FlexBox e Media Query API do Jetpack Compose de abril 2026. Exemplos práticos para UIs adaptativas."
date: "2026-04-29"
author: "Karina Melo"
---

# Compose Grid, FlexBox e Media Query: Guia Prático

Domine os novos layouts Grid, FlexBox e Media Query API do Jetpack Compose de abril 2026. Exemplos práticos para UIs adaptativas.


A release de abril de 2026 do Jetpack Compose trouxe algo que muitos desenvolvedores Android e multiplataforma pediam havia tempo: **componentes de layout de verdade para interfaces adaptativas**. Grid, FlexBox e Media Query API chegaram como APIs experimentais e prometem mudar a forma como construímos telas responsivas em Kotlin.

Se você trabalha com [Jetpack Compose](/tutoriais/jetpack-compose-basico/) no dia a dia, sabe que montar layouts complexos com `Row` e `Column` aninhados rapidamente vira uma dor de cabeça. Breakpoints manuais, cálculos de largura e lógica condicional espalhada por todo o Composable tornam o código difícil de manter. Os três novos componentes resolvem exatamente isso.

Neste artigo, vamos explorar cada API com exemplos práticos e prontos para copiar.

## O que mudou no Compose em abril de 2026?

A atualização trouxe três APIs experimentais que seguem padrões já consolidados no desenvolvimento web:

- **Grid**: layout bidimensional com linhas, colunas e spans
- **FlexBox**: distribuição flexível de itens com wrap e alinhamento em múltiplos eixos
- **Media Query API**: adaptação declarativa baseada em sinais do ambiente como tamanho de janela, postura do dispositivo e tipo de input

Além dessas, a release também incluiu uma nova **Styles API** para estilização baseada em estado e melhorias no suporte a trackpad. Mas o foco deste artigo são os três componentes de layout, que impactam diretamente a arquitetura de qualquer app adaptativo.

Se você já trabalha com [Compose Multiplatform](/blog/kotlin-compose-multiplatform-ui-2026/), essas APIs funcionam também no Desktop e Web, tornando ainda mais viável compartilhar código de UI entre plataformas.

## Grid: layouts bidimensionais de verdade

O componente `Grid` resolve o problema mais comum de quem precisa montar dashboards, galerias ou qualquer tela com disposição em grade. Antes, era preciso combinar `LazyVerticalGrid` com cálculos manuais. Agora, a API oferece controle total sobre tracks (linhas e colunas), gaps e spans.

### Exemplo básico: grade de cards

```kotlin
@OptIn(ExperimentalComposeApi::class)
@Composable
fun DashboardGrid() {
    Grid(
        config = {
            columns(4) { fraction(0.25f) }
            rows(2) { fraction(0.5f) }
            gap(16.dp)
        }
    ) {
        MetricCard(
            titulo = "Receita",
            valor = "R$ 42.500",
            modifier = Modifier.gridItem(rowSpan = 2)
        )
        MetricCard(
            titulo = "Usuarios",
            valor = "1.230",
            modifier = Modifier.gridItem(columnSpan = 2)
        )
        MetricCard(titulo = "Pedidos", valor = "89")
        MetricCard(titulo = "Conversao", valor = "3,2%")
    }
}
```

O `Grid` aceita diferentes unidades de dimensionamento: `Dp` fixo, frações (`Fr`), porcentagens e até tamanhos intrínsecos baseados no conteúdo. Isso permite criar grades que se adaptam naturalmente ao espaço disponível sem cálculos manuais.

### Exemplo avançado: adaptação por orientação

```kotlin
@OptIn(ExperimentalComposeApi::class)
@Composable
fun AdaptiveProductGrid(produtos: List<Produto>) {
    val configuration = LocalConfiguration.current
    val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE

    Grid(
        config = {
            if (isLandscape) {
                columns(4) { fraction(0.25f) }
            } else {
                columns(2) { fraction(0.5f) }
            }
            row { auto() }
            gap(horizontal = 12.dp, vertical = 16.dp)
        }
    ) {
        produtos.forEach { produto ->
            ProductCard(
                produto = produto,
                modifier = if (produto.destaque) {
                    Modifier.gridItem(columnSpan = 2)
                } else {
                    Modifier
                }
            )
        }
    }
}
```

Quem já construiu telas com [layouts em Compose](/tutoriais/jetpack-compose-layouts/) vai perceber que o `Grid` elimina boa parte da lógica condicional que antes era necessária para responsividade.

## FlexBox: distribuição inteligente de itens

O `FlexBox` segue a mesma filosofia do CSS Flexbox: distribuir itens dentro de um container com controle sobre direção, wrap, alinhamento e proporção. A grande vantagem sobre `Row` e `Column` é o suporte nativo a **wrap** — quando os itens não cabem em uma linha, eles quebram automaticamente para a próxima.

### Exemplo: barra de tags com wrap

```kotlin
@OptIn(ExperimentalComposeApi::class)
@Composable
fun TagBar(tags: List<String>) {
    FlexBox(
        config = {
            wrap(FlexWrap.Wrap)
            gap(8.dp)
            justifyContent(JustifyContent.Start)
            alignItems(AlignItems.Center)
        }
    ) {
        tags.forEach { tag ->
            TagChip(
                text = tag,
                modifier = Modifier.flex { shrink(0f) }
            )
        }
    }
}

@Composable
fun TagChip(text: String, modifier: Modifier = Modifier) {
    Surface(
        modifier = modifier,
        shape = RoundedCornerShape(16.dp),
        color = MaterialTheme.colorScheme.secondaryContainer
    ) {
        Text(
            text = text,
            modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
            style = MaterialTheme.typography.labelMedium
        )
    }
}
```

### Exemplo: layout de formulário adaptativo

```kotlin
@OptIn(ExperimentalComposeApi::class)
@Composable
fun AdaptiveForm() {
    FlexBox(
        config = {
            wrap(FlexWrap.Wrap)
            gap(horizontal = 16.dp, vertical = 12.dp)
        }
    ) {
        OutlinedTextField(
            value = "",
            onValueChange = {},
            label = { Text("Nome") },
            modifier = Modifier.flex {
                grow(1f)
                basis(200.dp)
            }
        )
        OutlinedTextField(
            value = "",
            onValueChange = {},
            label = { Text("Email") },
            modifier = Modifier.flex {
                grow(2f)
                basis(300.dp)
            }
        )
        OutlinedTextField(
            value = "",
            onValueChange = {},
            label = { Text("Telefone") },
            modifier = Modifier.flex {
                grow(1f)
                basis(150.dp)
            }
        )
    }
}
```

O `basis` define o tamanho mínimo preferido antes da distribuição do espaço extra via `grow`. Isso garante que os campos nunca fiquem menores do que o necessário, mas expandem proporcionalmente quando há espaço sobrando. Para quem já usou [Kotlin DSL](/blog/kotlin-dsl/) em outros contextos, a API do FlexBox segue o mesmo padrão de configuração declarativa.

## Media Query API: adaptação baseada no ambiente

A **Media Query API** é possivelmente a adição mais poderosa desta release. Ela permite que seu Composable reaja declarativamente a sinais do ambiente sem precisar de lógica imperativa espalhada pelo código.

### Sinais disponíveis

A API reconhece diversos sinais ambientais:

- **Tamanho da janela**: largura e altura em WindowSizeClass (compact, medium, expanded)
- **Postura do dispositivo**: flat, half-opened, tabletop (para dobráveis)
- **Tipo de teclado**: virtual ou físico
- **Precisão do ponteiro**: touch ou mouse
- **Orientação**: portrait ou landscape

### Exemplo: layout responsivo com Media Query

```kotlin
@OptIn(ExperimentalComposeApi::class)
@Composable
fun ResponsiveHomeScreen(viewModel: HomeViewModel) {
    val showSidebar = mediaQuery {
        windowWidthSizeClass >= WindowWidthSizeClass.Medium
    }

    val isTabletop = mediaQuery {
        windowPosture == UiMediaScope.Posture.Tabletop
    }

    if (isTabletop) {
        TabletopLayout(viewModel)
    } else if (showSidebar) {
        Row {
            NavigationSidebar(modifier = Modifier.width(280.dp))
            MainContent(
                viewModel = viewModel,
                modifier = Modifier.weight(1f)
            )
        }
    } else {
        Column {
            MainContent(
                viewModel = viewModel,
                modifier = Modifier.weight(1f)
            )
            BottomNavigation()
        }
    }
}
```

### Performance com derivedMediaQuery

Para sinais que mudam com alta frequência, a API oferece `derivedMediaQuery`, que otimiza recomposições usando `derivedStateOf` internamente:

```kotlin
@OptIn(ExperimentalComposeApi::class)
@Composable
fun AdaptiveGrid(items: List<Item>) {
    val columnCount = derivedMediaQuery {
        when {
            windowWidthSizeClass == WindowWidthSizeClass.Expanded -> 4
            windowWidthSizeClass == WindowWidthSizeClass.Medium -> 3
            else -> 2
        }
    }

    Grid(
        config = {
            columns(columnCount) { fraction(1f / columnCount) }
            gap(12.dp)
        }
    ) {
        items.forEach { item ->
            ItemCard(item)
        }
    }
}
```

Essa composição entre Grid e Media Query API mostra o verdadeiro poder das novas APIs trabalhando juntas. Se você já lida com [observabilidade em apps Kotlin](/blog/kotlin-observabilidade/), vale monitorar o impacto de recomposições usando essas ferramentas.

## Combinando Grid, FlexBox e Media Query

Na prática, as três APIs se complementam. Um cenário comum seria:

```kotlin
@OptIn(ExperimentalComposeApi::class)
@Composable
fun ProductCatalogScreen(produtos: List<Produto>, categorias: List<String>) {
    val isExpanded = mediaQuery {
        windowWidthSizeClass == WindowWidthSizeClass.Expanded
    }

    Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
        // Tags de filtro com wrap automático
        FlexBox(
            config = {
                wrap(FlexWrap.Wrap)
                gap(8.dp)
            }
        ) {
            categorias.forEach { cat ->
                FilterChip(selected = false, onClick = {}, label = { Text(cat) })
            }
        }

        Spacer(modifier = Modifier.height(16.dp))

        // Grade adaptativa de produtos
        Grid(
            config = {
                if (isExpanded) {
                    columns(4) { fraction(0.25f) }
                } else {
                    columns(2) { fraction(0.5f) }
                }
                gap(12.dp)
            }
        ) {
            produtos.forEach { produto ->
                ProductCard(produto)
            }
        }
    }
}
```

## Como habilitar as novas APIs

Todas as APIs desta release são **experimentais**. Para usá-las, adicione a dependência mais recente do Compose BOM e a anotação `@OptIn`:

```kotlin
// build.gradle.kts
dependencies {
    implementation(platform("androidx.compose:compose-bom:2026.04.00"))
    implementation("androidx.compose.foundation:foundation")
    implementation("androidx.compose.foundation:foundation-layout")
}
```

No código, use `@OptIn(ExperimentalComposeApi::class)` em cada Composable que utilize Grid, FlexBox ou Media Query.

Se você está configurando um projeto do zero, nosso tutorial de [Compose com Android Studio](/tutoriais/kotlin-android-studio/) cobre o setup inicial completo. Para projetos multiplataforma, o guia de [Compose Multiplatform Desktop](/blog/kotlin-compose-multiplatform-desktop/) mostra como compartilhar código de UI entre Android e Desktop.

## Quando usar cada componente

| Cenário | Componente |
|---------|-----------|
| Dashboard com cards em grade | Grid |
| Barra de tags ou chips com quebra de linha | FlexBox |
| Formulário com campos de tamanho variável | FlexBox |
| Layout completamente diferente por tamanho de tela | Media Query |
| Galeria de imagens com itens em destaque | Grid + Media Query |
| Adaptação para dispositivos dobráveis | Media Query |

## Conclusão

Grid, FlexBox e Media Query API representam a maior evolução de layout do Jetpack Compose desde o lançamento do framework. Juntas, elas eliminam a necessidade de gambiarras com `Row`/`Column` aninhados e lógica condicional espalhada pelo código.

Se você já domina os fundamentos do Compose, é hora de experimentar essas APIs em protótipos. Elas ainda são experimentais, mas a direção é clara: o Compose está se tornando um framework de layout tão poderoso quanto CSS Grid e Flexbox na web, com a vantagem de tipagem estática e integração nativa com o ecossistema Kotlin.

Para quem trabalha com [Kotlin Multiplatform](/blog/kotlin-multiplatform/), a boa notícia é que essas APIs fazem parte do Compose Foundation, disponível para Android, Desktop e Web. Combine isso com [Navigation 3](/blog/navigation-3-compose-android-2026/) e [Hot Reload](/blog/compose-hot-reload-kotlin-2026/) e você tem um toolkit completo para aplicações modernas. No ecossistema web, <a href="https://golang.com.br/blog/htmx-golang-templates-interatividade/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">Go tem explorado abordagens como HTMX para UIs reativas no servidor</a>, mas o Compose oferece uma experiência declarativa nativa que dispensa JavaScript no client. Linguagens como <a href="https://rustlang.com.br/blog/rust-egui-gui-nativa/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'rustlang.com.br' })">Rust com egui também investem em UI declarativa</a>, mostrando que esse paradigma está se consolidando além do ecossistema Android.

Se você está migrando de XML para Compose, nosso guia de [Jetpack Compose completo](/guias/guia-jetpack-compose/) cobre a transição passo a passo. E para entender como a nova [desestruturação por nome do Kotlin](/blog/kotlin-name-based-destructuring-2026/) pode simplificar seu código de UI com data classes, confira o artigo complementar.

---

## Perguntas frequentes

### O Grid do Compose substitui LazyVerticalGrid?

Não diretamente. O `Grid` é voltado para layouts fixos e responsivos com controle de tracks e spans. O `LazyVerticalGrid` continua sendo a melhor opção para listas longas com reciclagem de itens. Use `Grid` para dashboards e layouts de página, e `LazyVerticalGrid` para feeds e catálogos com scroll infinito.

### FlexBox funciona em Compose Multiplatform?

Sim. O FlexBox faz parte do `foundation-layout`, que está disponível em todas as plataformas suportadas pelo Compose Multiplatform: Android, Desktop (JVM), iOS e Web (via Kotlin/Wasm). A API é a mesma em todas as plataformas.

### A Media Query API recompoe muito e prejudica performance?

A API foi projetada com otimização em mente. Ela usa `derivedStateOf` internamente para sinais de alta frequência, e o `derivedMediaQuery` permite controle fino sobre quando recomposições acontecem. Na prática, a performance é comparável a verificar `LocalConfiguration.current` manualmente.

### Preciso de alguma versão mínima do Android para usar Grid e FlexBox?

As APIs experimentais do Compose seguem o suporte padrão do Compose Foundation, que funciona a partir do Android API 21 (Lollipop). A Media Query API para detecção de postura em dobráveis requer a biblioteca WindowManager da Jetpack e dispositivos compatíveis.
