Modifier — cadeia de modificadores e desempenho no Compose

Autor: IT Sectr Publicado: 2026-06-28 Tempo de leitura: 8 min

Modifier é um objeto imutável no Jetpack Compose que define as propriedades de um componente de UI: tamanho, preenchimento, fundo, manipulação de gestos e comportamento. Os modificadores são combinados em uma cadeia por meio de chamadas sequenciais, e a ordem de sua aplicação afeta criticamente o resultado. De acordo com Google Android Developers, 2026, o uso correto de Modifier é a base para construir interfaces flexíveis e de alto desempenho em UI declarativa.

Principais conclusões

  • Modifier é um objeto imutável que descreve a aparência e o comportamento de um componente de UI
  • Cadeia de modificadores é construída sequencialmente, a ordem afeta a exibição
  • Ordem importa: padding → size difere de size → padding
  • Modifier.composed permite criar modificadores compostos personalizados
  • Otimização: evite recriar Modifier em cada recomposição

O que é Modifier no Jetpack Compose

Modifier é uma interface do pacote androidx.compose.ui que implementa o padrão Composite. Cada modificador é um elemento de cadeia que envolve o anterior e adiciona seu próprio comportamento. Modifier é imutável — qualquer alteração cria um novo objeto por meio de cópia com um novo elemento adicionado à cadeia. Isso permite compartilhar com segurança um único Modifier entre vários componentes.

As funções modificadoras básicas são chamadas por meio do objeto complementar Modifier (por exemplo, Modifier.padding(), Modifier.fillMaxWidth()). Cada função retorna um novo Modifier com o elemento adicionado. Se houver vários modificadores, eles são combinados em uma cadeia: Modifier.padding(16.dp).fillMaxWidth().background(Color.Blue). A ordem vai de externo para interno em relação ao elemento de UI.

Ao contrário das Views tradicionais onde as propriedades eram definidas via setters (view.setPadding(...), view.setBackground(...)), no Compose Modifier é uma descrição declarativa. O componente não "aplica" os modificadores em tempo de execução — o LayoutNode percorre a cadeia Modifier durante a composição e constrói uma lista de Modifier.Element que são processados durante as fases de medição e layout.

Cadeia de modificadores e ordem de aplicação

Ordem dos modificadores é um dos erros mais comuns no Compose. Cada modificador envolve o anterior, e as operações são aplicadas de fora para dentro. Por exemplo, padding(16.dp).clickable { }: primeiro o preenchimento é adicionado ao redor do elemento, depois a área de clique inclui o preenchimento. clickable { }.padding(16.dp): a área de clique é igual ao tamanho do elemento primeiro, depois o preenchimento é adicionado ao redor — clicar no preenchimento não funcionará.

Regra de memorização: leia a cadeia da esquerda para a direita e aplique de fora para dentro. O primeiro modificador é o mais externo, aplicado à área ao redor do elemento. O último é o mais interno, aplicado diretamente ao conteúdo. Os modificadores de tamanho (size, fillMaxWidth) devem vir após o preenchimento se o preenchimento for necessário do pai, ou antes do preenchimento se o conteúdo deve ser primeiro restringido e depois centralizado.

Exemplo: size(100.dp).padding(10.dp) — elemento de tamanho fixo 100dp, depois preenchimento de 10dp por fora (tamanho final 120dp). padding(10.dp).size(100.dp) — o preenchimento de 10dp reduz o espaço disponível para (pai - 20dp), então size(100dp) pode exceder o pai. Sempre pense na ordem deliberadamente, usando testes de exibição para verificar o resultado.

OrdemResultado
padding → clickableClique funciona também na área de preenchimento
clickable → paddingClique funciona apenas no conteúdo, preenchimento é zona morta
size → paddingElemento size(100), preenchimento por fora → 100+2*pad
padding → sizePreenchimento reduz espaço, size pode exceder limites
background → paddingFundo preenche todo o elemento incluindo área externa
padding → backgroundFundo apenas dentro do preenchimento (área externa transparente)

Tipos de modificadores: tamanho, preenchimento, decoração e comportamento

A biblioteca padrão do Compose inclui ~50+ modificadores divididos em categorias. Tamanho e posicionamento: Modifier.size(), width(), height(), fillMaxSize(), fillMaxWidth(), fillMaxHeight(), defaultMinSize(), requiredSize(). Preenchimento e bordas: padding(), offset(), margin (definido via preenchimento do pai ou Layout). Decoração: background(), border(), clip(), alpha(), shadow(), blur().

Comportamento e gestos: clickable(), combinedClickable(), pointerInput(), draggable(), swipeable(). Layout em contêiner: weight() (para Row/Column), align(), alignBy(), matchParentSize(). Semântica e acessibilidade: semantics(), testTag(), clearAndSetSemantics(). Desenho: drawBehind(), drawWithContent(), drawModifier() — modificadores que permitem desenho personalizado no canvas.

Modificadores semânticos são uma categoria especial. Modifier.semantics {} define como o elemento será representado na árvore de Acessibilidade. O Compose preenche automaticamente a semântica a partir do texto, mas componentes personalizados precisam de papéis, estados e ações definidos manualmente. Isso é crítico para a conformidade com WCAG 2.2 e o funcionamento correto do TalkBack (Android) e VoiceOver (iOS).

kotlin
@Composable
fun ModifierDemo() {
    // Cadeia de modificadores com ordem correta
    Box(
        modifier = Modifier
            .size(150.dp)
            .padding(8.dp)
            .border(2.dp, Color.Gray)
            .background(Color(0xFFE3F2FD))
            .clickable { /* handle click */ }
            .semantics {
                contentDescription = "Demo card with click action"
                role = Role.Button
            }
    ) {
        Text("Toque-me")
    }
}

Criação de modificadores personalizados via Modifier.composed

Modifier.composed é um método de fábrica que permite criar modificadores compostos que podem usar outros modificadores, LocalComposition e estado local. Ao contrário de uma função de extensão regular, composed cria uma instância toda vez que é aplicado, permitindo que o modificador tenha seu próprio estado.

Quando usar composed: combinações recorrentes de modificadores (por exemplo, estilo de cartão padrão: padding + background + border + clickable); modificadores com estado (mudança de fundo animada ao pressionar); acesso a CompositionLocals (esquema de cores do MaterialTheme, densidade de pixels). Para casos comuns, uma função de extensão regular sem composed é suficiente.

Desempenho de composed: cada chamada cria um novo objeto modificador, o que pode levar a alocações extras durante a recomposição. Para evitar isso, envolva composed em remember. O Google recomenda usar composed apenas quando estado ou CompositionLocal são realmente necessários internamente. Para combinações estáticas, use funções de extensão regulares.

kotlin
// Modificador personalizado via composed com estado
fun Modifier.cardStyle(
    elevation: Dp = 4.dp,
    isSelected: Boolean = false
): Modifier = this.composed {
    val backgroundColor = if (isSelected)
        MaterialTheme.colorScheme.primaryContainer
    else
        MaterialTheme.colorScheme.surface

    this
        .fillMaxWidth()
        .padding(12.dp)
        .background(backgroundColor, RoundedCornerShape(8.dp))
        .shadow(elevation, RoundedCornerShape(8.dp))
}

// Exemplo de uso
@Composable
fun CardList() {
    Column {
        Box(Modifier.cardStyle()) { Text("Item 1") }
        Box(Modifier.cardStyle(isSelected = true)) { Text("Selecionado") }
    }
}

// Versão estática (sem composed) — mais rápida
fun Modifier.simpleCardStyle(): Modifier =
    this.fillMaxWidth().padding(8.dp).clip(RoundedCornerShape(4.dp))

Desempenho do Modifier e melhores práticas

Evite recriar Modifier em cada recomposição. Se o modificador não depende de dados mutáveis — mova-o para uma constante ou remember. Cada chamada a Modifier.padding().background() cria novos objetos Modifier.Element. Em um componente isolado isso é insignificante, mas em um LazyColumn com centenas de elementos, alocações extras causam atraso perceptível na rolagem.

Regra: se a cadeia de modificadores não depende dos parâmetros da função Composable — declare-a como val fora da função (no nível de arquivo ou Companion). Se depender — use remember(dependência) { ... }. Para modificadores que são sempre iguais, val fora do Composable é mais eficiente: tais objetos são criados uma vez durante toda a vida útil do aplicativo.

Melhores práticas de ordenação de Modifier: coloque os modificadores em ordem lógica: primeiro tamanho/preenchimento (layout), depois decoração (background, border), depois comportamento (clickable, pointerInput). Isso não só melhora a legibilidade, mas também ajuda o Compose Runtime a otimizar a cadeia durante a medição. Evite também elementos Box aninhados excessivos com diferentes Modifier — frequentemente um único Modifier no contêiner pai pode substituir 2-3 aninhados.

kotlin
// ✅ Bom: constante fora do Composable
private val cardModifier = Modifier
    .fillMaxWidth()
    .padding(16.dp)
    .clip(RoundedCornerShape(8.dp))

@Composable
fun CardContent() {
    Box(cardModifier.background(Color.White)) { ... }
}

// ❌ Ruim: recriação em cada recomposição
@Composable
fun BadCard() {
    Box(Modifier.fillMaxWidth().padding(16.dp)) { ... }
}

// ✅ Bom: remember para Modifier dinâmico
@Composable
fun DynamicCard(color: Color) {
    val modifier = remember(color) {
        Modifier.fillMaxWidth().background(color)
    }
    Box(modifier) { ... }
}

Perguntas frequentes

Posso usar um mesmo Modifier para vários elementos Composable?

Sim, Modifier é imutável, então um objeto pode ser usado com segurança em vários lugares. No entanto, se você usar um modificador composed, cada chamada cria uma nova instância. Para cadeias estáticas, uma constante ou val fora do Composable é a solução ideal.

Como depurar uma cadeia de modificadores?

Use o Layout Inspector no Android Studio — ele mostra visualmente os limites de cada Modifier. Para depuração programática, adicione Modifier.border() com cores diferentes em cada etapa da cadeia para ver os limites de cada modificador.

O que é Modifier.then() e como é diferente de chamadas sequenciais?

Modifier.then(other) anexa a cadeia other a this. Chamadas sequenciais (Modifier.a().b()) são equivalentes a Modifier.then(a()).then(b()). Não há diferença — é o mesmo mecanismo de cadeia. then() é útil quando você precisa anexar uma cadeia pronta de uma variável.

Como Modifier afeta a semântica de Acessibilidade?

Modifier.semantics {} define como o elemento será descrito para um leitor de tela. Modifier.clickable() adiciona automaticamente o papel de Botão e Action(OnClick). Para gestos personalizados, você precisa especificar explicitamente semantics. Sem modificadores semânticos, os usuários do TalkBack não poderão interagir com componentes personalizados.

Por que background no Modifier não funciona com cantos arredondados?

Modifier.background(color, shape) funciona com cantos, mas clip() deve vir ANTES do background para que os cantos sejam recortados. Ordem correta: clip(shape).background(color). Se precisar recortar o conteúdo interno também, use clipToBounds() no pai.

Resumo

  • Modifier é um objeto imutável para descrever declarativamente aparência e comportamento
  • Ordem dos modificadores determina o resultado: padding → clickable vs clickable → padding
  • Cadeia é construída sequencialmente, cada elemento envolve o anterior
  • Modifier.composed permite criar modificadores com estado e CompositionLocal
  • Desempenho: mova cadeias estáticas para constantes, use remember para dinâmicas
  • Semântica: Modifier.semantics é obrigatório para Acessibilidade de componentes personalizados
  • Recomendação: organize modificadores do layout para decoração, depois para comportamento

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também