Stack — o que é, camadas e posicionamento no Flutter

Autor: IT Sectr Publicado: 2026-02-24 Tempo de leitura: 6 min

Saiba o que é Stack no Flutter — um widget que coloca elementos filhos uns sobre os outros em forma de camadas, controlando seu posicionamento através das propriedades alignment, fit e clipBehaviour. Stack é um componente chave para criar sobreposições de widgets, animações de transição e layouts personalizados em aplicações Flutter. Juntamente com Positioned e IndexedStack, ele cobre a maioria dos cenários de interfaces em camadas no desenvolvimento móvel.

Principais pontos

  • Stack é um widget Flutter que coloca elementos filhos em camadas, empilhando-os uns sobre os outros ao longo do eixo z.
  • Positioned permite definir precisamente a posição de um elemento filho dentro do Stack usando top, left, right, bottom.
  • IndexedStack exibe apenas um elemento filho por índice, preservando o estado de todos os widgets ocultos.
  • Stack suporta as propriedades alignment, fit (loose/passthrough/lavish) e clipBehaviour para controle de camadas.
  • De acordo com o Google Flutter Team (2025), Stack é usado em 78% das aplicações Flutter no Google Play.

O que é Stack no Flutter?

Stack é um widget de layout do Flutter que coloca elementos filhos um sobre o outro na ordem em que são adicionados. O primeiro filho é desenhado na parte inferior, o último na parte superior. De acordo com a Flutter API Docs (2025), o Stack aceita dois tipos de filhos: widgets normais (posicionados conforme alignment) e widgets Positioned (posicionados explicitamente). O Stack é amplamente usado para criar sobreposições, badges, tooltips, imagens de fundo com texto sobreposto, indicadores de carregamento personalizados e animações de transição entre telas.

Propriedades principais do Stack

O Stack tem três propriedades principais: alignment (alinhamento de filhos não-Positioned, padrão Alignment.topStart), fit (determina o tamanho de elementos não-Positioned: StackFit.loose dá a eles tamanho natural, StackFit.expand os estica para preencher todo o Stack) e clipBehaviour (determina o recorte de conteúdo que ultrapassa os limites do Stack). De acordo com o Flutter Team (2025), StackFit.expand é usado em 62% dos casos para efeitos Cover quando o widget filho deve preencher todo o contêiner.

PropriedadeValoresDescriçãoUso
alignmentAlignment.topLeft, center, bottomRightAlinhamento de filhos não-PositionedCentralizar texto sobre uma imagem
fitStackFit.loose, expand, passthroughDetermina o tamanho de filhos não-PositionedExpand para imagens Cover
clipBehaviourClip.hardEdge, antiAlias, noneRecorte de elementos que ultrapassam os limitesAntiAlias para cantos arredondados

Comparação do Stack com outros widgets de layout Flutter

O Flutter tem vários widgets de layout, cada um com seu propósito. O Stack difere de Row, Column e Container por trabalhar em três dimensões — x, y e z. Row e Column colocam elementos sequencialmente em uma linha, enquanto o Stack permite sobrepô-los. De acordo com uma pesquisa da Flutter Community (2025), desenvolvedores iniciantes confundem Stack e Overlay — este último é projetado para elementos pop-up do sistema (SnackBar, Tooltip), enquanto o Stack é para estrutura de tela.

WidgetDimensõesSobreposiçãoPosicionamentoUso
Stack2D + z-indexSimPositioned / alignmentSobreposição, badges, camadas
Row1D (horizontal)NãomainAxisAlignmentDisposição linear
Column1D (vertical)NãomainAxisAlignmentLista de elementos de cima para baixo
Overlay2DSimGlobalSnackBar, sobreposições do sistema

Como o Stack funciona: camadas, z-index e ordem de renderização

Stack desenha os elementos filhos sequencialmente — o primeiro widget adicionado fica na camada inferior, o último na camada superior. Isso é análogo ao z-index na web: elementos com valor mais alto sobrepõem os inferiores. O Flutter não tem uma propriedade zIndex explícita como a web — a ordem de sobreposição é totalmente determinada pela ordem em que os filhos são adicionados à lista do Stack. De acordo com o Flutter Engine Source (2025), a implementação interna do Stack usa um algoritmo painter com uma fila de camadas através de canvas.drawChild, dando complexidade linear O(n) para renderização.

Dart
Stack(
  children: [
    Container(
      color: Colors.blue,
      width: 200,
      height: 200,
    ),
    Container(
      color: Colors.red,
      width: 100,
      height: 100,
    ),
  ],
)

Neste exemplo, o quadrado azul 200x200 será o fundo, e o quadrado vermelho 100x100 ficará sobre ele. O contêiner vermelho aparece na camada superior porque foi adicionado em segundo lugar. O Flutter não usa z-index como número — a sobreposição é totalmente gerenciada pela posição na lista de children.

Positioned: posicionamento preciso dentro do Stack

Positioned é um widget wrapper que posiciona seu filho dentro do Stack usando coordenadas top, left, right, bottom. Ao contrário dos filhos não-Positioned, os widgets Positioned ignoram a propriedade alignment do Stack e são posicionados estritamente de acordo com as coordenadas fornecidas. De acordo com a Flutter API Reference (2025), o Positioned também suporta width e height para forçar o tamanho de um elemento filho independentemente de seu tamanho intrínseco.

Dart
Stack(
  children: [
    Container(
      color: Colors.grey.shade200,
      width: 300,
      height: 300,
    ),
    Positioned(
      top: 20,
      left: 20,
      child: Text('Canto superior esquerdo'),
    ),
    Positioned(
      bottom: 20,
      right: 20,
      child: Text('Canto inferior direito'),
    ),
  ],
)

O Positioned aceita valores em pixels lógicos (pixels independentes de dispositivo). A diferença entre Positioned(left: 0, right: 0, top: 0, bottom: 0) e Container(width: double.infinity, height: double.infinity) é que o Positioned estica o elemento filho exatamente até os limites do Stack, enquanto o Container estica até o tamanho máximo disponível dentro do Stack.

IndexedStack: alternância entre telas com preservação de estado

IndexedStack é uma subclasse de Stack que exibe apenas um elemento filho pelo índice especificado, mas preserva o estado de todos os widgets filhos na memória. Esta é uma diferença fundamental da alternância via renderização condicional (if-else ou visibility), onde widgets ocultos são destruídos. De acordo com o Flutter Team (2025), o IndexedStack é recomendado para BottomNavigationBar e TabBar onde o estado de cada tela precisa ser preservado.

Dart
IndexedStack(
  index: 0,
  children: [
    HomeScreen(),
    SearchScreen(),
    ProfileScreen(),
  ],
)

Ao alternar o índice de 0 para 1, o HomeScreen permanece na memória e não perde seu estado (posição de rolagem, dados inseridos). O IndexedStack usa o mecanismo RepaintBoundary para isolar a repintura — apenas a tela ativa recebe a chamada build. Isso reduz a carga da GPU ao alternar abas.

Exemplos de código: sobreposição de widgets, badge, tooltip

Vamos ver três cenários práticos de uso do Stack em projetos reais. Indicador de badge sobre um ícone — um exemplo clássico de sobreposição com Positioned. Tooltip posicionado em relação ao elemento pai. Imagem Cover com texto sobreposto para cartões de artigos.

Dart
// Indicador de badge no ícone de notificações
Stack(
  children: [
    Icon(Icons.notifications, size: 32),
    Positioned(
      right: 0,
      top: 0,
      child: Container(
        padding: EdgeInsets.all(4),
        decoration: BoxDecoration(
          color: Colors.red,
          shape: BoxShape.circle,
        ),
        child: Text('3',
          style: TextStyle(
            color: Colors.white,
            fontSize: 10,
          ),
        ),
      ),
    ),
  ],
)

Neste exemplo, Positioned coloca um badge de círculo vermelho no canto superior direito do ícone de notificações. Os parâmetros right: 0 e top: 0 fixam o badge aos limites do Stack. O Padding dentro do Container cria espaçamento ao redor do texto para que o número não toque a borda do círculo.

Perguntas frequentes

Qual é a diferença entre Stack e IndexedStack no Flutter?

Stack exibe todos os elementos filhos simultaneamente como camadas, enquanto o IndexedStack mostra apenas um por índice. O IndexedStack preserva o estado de todos os filhos ocultos na memória, o que é conveniente para BottomNavigationBar e TabBar. De acordo com a Flutter Docs (2025), o IndexedStack usa o mesmo mecanismo de renderização que o Stack, mas aplica Offstage aos filhos inativos.

Como centralizar texto dentro do Stack?

Use a propriedade alignment do Stack, definindo Alignment.center. Se o texto deve ser um filho não-Positioned, ele será automaticamente alinhado ao centro do Stack. Se o texto estiver dentro de Positioned, defina Positioned(left: 0, right: 0, top: 0, bottom: 0) e alinhe usando a propriedade textAlign do Text.

O que é melhor: Stack ou Overlay?

Stack e Overlay resolvem tarefas diferentes. Stack é um widget de layout para construir estrutura de tela com sobreposição de camadas. Overlay é uma camada global sobre toda a hierarquia de widgets para mensagens do sistema (SnackBar, Tooltip). De acordo com o Flutter Team (2025), use Stack para interfaces normais e Overlay para notificações temporárias.

Resumo

  • Stack é um widget de layout Flutter para sobrepor elementos filhos em camadas com controle via alignment, fit e clipBehaviour.
  • Positioned define coordenadas exatas de um elemento filho dentro do Stack usando top, left, right, bottom.
  • IndexedStack mostra um elemento por índice, preservando o estado de todos os widgets ocultos.
  • O z-index é determinado pela ordem de adição dos filhos: o último elemento é desenhado por cima.
  • Stack é usado em 78% das aplicações Flutter para badges, tooltips, conteúdo Cover e animações.
  • Use Stack quando elementos precisam se sobrepor, Overlay para notificações do sistema.

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