Flexible é um widget Flutter que controla como um elemento filho ocupa o espaço disponível em um contêiner Flex. Diferente do Expanded, Flexible não força o filho a preencher toda a área alocada — o widget filho pode ser menor, e o espaço restante permanece vazio. De acordo com a documentação oficial do Flutter (2026), Flexible é necessário em cenários onde é necessária distribuição flexível de espaço sem estiramento forçado: botões com largura mínima, blocos de texto com tamanho natural e elementos com intrinsic constraints.
Pontos Principais
Flexible é um widget wrapper que fornece espaço flexível a um elemento filho em um contêiner Flex. Flexible, assim como Expanded, participa da distribuição do espaço livre, mas com uma diferença chave: o filho de Flexible pode ocupar menos espaço do que o alocado se seu próprio tamanho for menor que o espaço disponível.
Flexible usa o algoritmo Flex do Flutter para calcular o espaço disponível. Primeiro, o framework consulta todos os filhos não flexíveis (widgets sem Flexible/Expanded) e calcula seu tamanho intrínseco. O espaço restante é dividido entre os filhos flexíveis proporcionalmente aos seus fatores flex. Após a alocação de espaço, Flexible verifica o fit — se for loose, o filho recebe uma restrição de “não maior que o alocado”, permitindo que ele permaneça pequeno.
Uma característica do Flexible: se o widget filho tem seus próprios tamanhos mínimos (por exemplo, Text com uma string longa), Flexible aloca o espaço solicitado sem estiramento forçado. Isso torna Flexible indispensável para elementos cujo tamanho deve ser determinado pelo conteúdo, não pelo contêiner.
Em resumo: use Flexible quando precisar reservar espaço para um elemento, mas não forçá-lo a esticar. Isso preserva os tamanhos naturais do conteúdo enquanto mantém a distribuição flexível do layout.
FlexFit é uma enumeração de dois valores: tight e loose. A escolha do fit determina se o widget filho será esticado à força até o tamanho do espaço alocado.
FlexFit.tight: o elemento filho recebe tight constraints — os tamanhos mínimo e máximo são iguais ao espaço alocado. O filho deve ocupar exatamente o espaço que o algoritmo Flex alocou. Se o filho for menor — ele estica. Se for maior — ele encolhe. O comportamento é idêntico ao Expanded.
FlexFit.loose: o elemento filho recebe loose constraints — o tamanho mínimo é 0, o máximo é igual ao espaço alocado. O filho pode ter qualquer tamanho de 0 ao máximo. Se o filho for pequeno (por exemplo, Text com uma string curta), ele ocupa sua largura natural e o espaço restante fica vazio.
Em resumo: FlexFit.loose é a escolha para blocos de texto e elementos com tamanho natural. FlexFit.tight é para layouts de coluna rigorosos onde todos os elementos devem ter a mesma largura ou altura.
Flexible e Expanded parecem semelhantes, mas resolvem tarefas diferentes. Expanded sempre estica o filho para preencher todo o espaço disponível. Flexible pode deixar espaço vazio ao redor do filho se o tamanho do conteúdo for menor que a parcela alocada.
Cenário para Flexible: dentro de uma Row há dois botões. O primeiro — “Comprar” (texto curto), o segundo — “Adicionar ao Carrinho” (texto longo). Com Expanded, ambos os botões esticam para a mesma largura, e o texto curto terá um padding enorme. Com Flexible, cada botão ocupa a largura do seu texto e o espaço livre fica entre eles ou nas bordas.
Cenário para Expanded: dentro de uma Column há três cartões que devem ocupar a mesma altura independentemente do conteúdo. Expanded divide uniformemente a altura disponível e cada cartão estica para o mesmo tamanho. Flexible com loose não funcionaria aqui — um cartão pequeno permaneceria pequeno, quebrando o design uniforme.
Em resumo: escolha Flexible quando o conteúdo determina o tamanho do elemento e o espaço vazio ao redor é aceitável. Escolha Expanded quando todos os elementos devem ter o mesmo tamanho independentemente do conteúdo.
Exemplo 1 demonstra o uso básico de Flexible com FlexFit.loose em uma Row.
Row(
children: [
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.amber,
child: const Text('curto'),
),
),
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.cyan,
child: const Text('texto longo para demonstração'),
),
),
],
)
No exemplo, ambos os Flexible usam loose fit. O primeiro contêiner com texto curto ocupa sua largura natural. O segundo com texto longo — a sua. Row aloca para cada um metade da largura disponível, mas o loose fit permite que os contêineres sejam menores e o espaço livre fica vazio entre eles.
Exemplo 2 — comparação de Flexible com Tight e Loose fit em uma Column.
Column(
children: [
Flexible(
fit: FlexFit.tight,
child: const Card(
child: ListTile(
title: Text('Tight — altura total esticada'),
),
),
),
const SizedBox(
height: 8,
),
Flexible(
fit: FlexFit.loose,
child: const Card(
child: ListTile(
title: Text('Loose — altura natural'),
),
),
),
],
)
Na Column, o primeiro Flexible (tight) estica o Card para metade da altura disponível. O segundo Flexible (loose) — o Card ocupa a altura conforme seu conteúdo e o espaço restante fica vazio. Visualmente, pode-se ver como tight preenche à força a área, enquanto loose preserva um tamanho compacto.
Em resumo: em código de produção, Flexible com loose é usado para campos de formulário, botões e blocos de texto. Flexible com tight é equivalente a Expanded e é usado para distribuição uniforme.
Erro 1: usar Flexible fora de um contêiner Flex. Assim como Expanded, Flexible lança uma LayoutException se não estiver dentro de Row, Column ou Flex. Solução: sempre verifique a cadeia de widgets pai.
Erro 2: confundir Flexible e Expanded. Desenvolvedores frequentemente usam Expanded quando precisam de Flexible com loose fit, e vice-versa. Resultado: Expanded estica um elemento com texto curto, criando grandes margens vazias. Solução: se o tamanho do elemento pode ser menor que o alocado — use Flexible(fit: FlexFit.loose).
Erro 3: fator flex zero. Flexible com flex=0 se comporta como um widget não flexível, o que pode ser não intuitivo. O desenvolvedor espera comportamento flexível, mas o elemento ocupa o tamanho mínimo. Solução: flex deve ser ≥1 para distribuição ativa de espaço.
Erro 4: Flexible dentro de uma ScrollView sem restrições de tamanho. Se Flexible está em uma Column dentro de SingleChildScrollView, o contêiner de scroll fornece espaço infinito e a distribuição flex não funciona. Solução: restrinja o tamanho do contêiner de scroll usando SizedBox ou ConstrainedBox.
Em resumo: Flexible requer a mesma atenção ao contexto pai que Expanded. A única diferença é o fit — escolha-o deliberadamente com base na tarefa.
Perguntas Frequentes
Expanded é Flexible com fit=tight fixo. A diferença é que Expanded tem uma vinculação rígida a preencher todo o espaço disponível, enquanto Flexible pode usar loose fit para preservar o tamanho natural do filho.
Para botões com diferentes comprimentos de texto, use Flexible(fit: FlexFit.loose). Cada botão ocupará a largura do seu conteúdo e não haverá desproporção entre eles. Expanded fará todos os botões terem a mesma largura.
Defina fit: FlexFit.tight — Flexible forçará o filho a preencher todo o espaço alocado. Neste modo, Flexible é completamente idêntico ao Expanded em comportamento.
Sim, se o filho for maior que o espaço alocado. Flexible passa restrições com um tamanho máximo igual à parcela do contêiner Flex. Se o filho exceder este tamanho, ele encolhe dentro das restrições.
Sim, Flexible funciona com qualquer contêiner Flex, incluindo Row, Column e o widget base Flex com direção arbitrária. Flex permite definir direções não padrão através de mainAxisAlignment e crossAxisAlignment.
Resumo
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.
Leia também