Pare de quebrar sua interface: aprenda LayoutBuilder como um verdadeiro profissional de Flutter.

Se você já projetou uma interface de usuário perfeita em cada detalhe…
…apenas para vê-la desmoronar completamente em um celular menor, um tablet maior ou no “celular de 2010 do seu amigo que se recusa a morrer”, então bem-vindo à realidade do Flutter.

A maioria das interfaces de usuário apresenta problemas porque o widget não tem ideia de quanto espaço realmente possui. É como tentar decorar um cômodo sem saber suas dimensões — é claro que os móveis não vão caber.

O Flutter tem uma solução para isso, e é poderosa:

O que é o LayoutBuilder?

Você pode já ter se deparado com estes erros frustrantes:

1. RenderBox was not laid out

Isso acontece quando um widget tenta se organizar sem conhecer suas restrições exatas.
É como arrumar móveis em um quarto escuro — você não sabe onde estão as paredes.

2. BoxConstraints força uma largura/altura infinita.

Este erro ocorre quando se espera que um widget se ajuste ao seu tamanho dentro de um espaço “infinito” — algo impossível no Flutter.

Ambos os erros são basicamente o Flutter gritando:

“Seu widget NÃO sabe o espaço que recebe!”

Como o LayoutBuilder resolve isso

Ao envolver um widget com LayoutBuilder, o Flutter passa as restrições exatas durante o layout:

LayoutBuilder ( 
  builder : (context, constraints) { 
    // constraints.maxWidth 
    // constraints.maxHeight 
    // constraints.minHeight 
    // constraints.minWidth

   }, 
)

Eu entendo maxWidth e maxHeight…
mas qual é a utilidade de minWidth e minHeight se eles são quase sempre zero?

Pode parecer que não importam.
Mas, na verdade, elas revelam algo muito importante sobre o quão rígido ou flexível é o widget pai .

Vamos analisar isso passo a passo.

Por que minWidth/minHeight parecem ser sempre zero?

Em muitos layouts comuns — como RowColumnStack, e ListView— o elemento pai NÃO força seus elementos filhos a terem um tamanho mínimo.

Assim, as restrições geralmente se parecem com:

larguraMínima = 0   
larguraMáxima = larguraDisponível

O que minWidth/minHeight realmente indicam?

Representam o espaço mínimo garantido para o seu widget .

Então:

  • Se minWidth = 0→ o pai for flexível
  • Se minWidth > 0→ o pai estiver impondo um limite mínimo
  • Se minWidth = maxWidth→ o pai estiver impondo uma restrição rígida

É assim que você percebe o quão rigorosos seus pais são em relação ao tamanho das roupas .

Em que parte eu deveria envolver o LayoutBuilder?

Agora que você entende o que o LayoutBuilder oferece — as restrições exatas que seu widget recebe — a próxima grande questão é:

Isso é importante porque o LayoutBuilder só faz sentido quando você o envolve no nível correto da árvore de widgets.
Envolvê-lo muito acima resulta em restrições que afetam todo o dispositivo.
Envolvê-lo muito abaixo resulta nas mesmas restrições que você já conhece.
Envolvê-lo corretamente desbloqueia layouts poderosos e responsivos.

Vamos analisar isso passo a passo.

Quando os pais impõem restrições flexíveis ou pouco claras.

Widgets como RowColumnExpanded, e Flexiblefrequentemente criam situações em que seu filho:

  • largura/altura imprevisíveis
  • zero tamanhos mínimos
  • restrições rígidas ou frouxas
  • possibilidade de colapso

LayoutBuilderajuda você a ver e a reagir a isso.

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(home: Demo()));
}

class Demo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("LayoutBuilder Demo")),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(height: 20),

          Text(
            "1️ Dentro de uma Row (obtém minWidth = 0)",
            style: TextStyle(fontSize: 18),
          ),
          SizedBox(height: 8),
          Row(
            children: [
              Expanded(child: LayoutBuilderBox(color: Colors.blue)),
              Container(width: 80, height: 50, color: Colors.red),
            ],
          ),

          SizedBox(height: 30),

          Text(
            "2️ Dentro do SizedBox (obtem o tamanho Exato)",
            style: TextStyle(fontSize: 18),
          ),
          SizedBox(height: 8),
          Center(
            child: SizedBox(
              width: 200,
              height: 150,
              child: LayoutBuilderBox(color: Colors.green),
            ),
          ),

          SizedBox(height: 30),

          Text(
            "3️ Dentro do Padding (constraints shrink)",
            style: TextStyle(fontSize: 18),
          ),
          SizedBox(height: 8),
          Padding(
            padding: const EdgeInsets.all(30),
            child: LayoutBuilderBox(color: Colors.orange),
          ),
        ],
      ),
    );
  }
}

class LayoutBuilderBox extends StatelessWidget {
  final Color color;
  const LayoutBuilderBox({required this.color});

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, c) {
        return Container(
          color: color,
          alignment: Alignment.center,
          child: Text(
            """minWidth: ${c.minWidth.toStringAsFixed(0)}  
maxWidth: ${c.maxWidth.toStringAsFixed(0)} 
minHeight: ${c.minHeight.toStringAsFixed(0)}  
maxHeight: ${c.maxHeight.toStringAsFixed(0)}""",
            style: TextStyle(color: Colors.white, fontSize: 16),
            textAlign: TextAlign.center,
          ),
        );
      },
    );
  }
}

Como NÃO usar o LayoutBuilder (aprendi isso da pior maneira 😭)

A esta altura, você provavelmente se sente poderoso com o LayoutBuilder.
Você vê as restrições. Você as entende.
Você sussurra para elas como um verdadeiro mestre da interface do usuário.

Mas espere aí — o LayoutBuilder é como eletricidade:
super útil, super legal… e super fácil de se queimar.

1. Não altere o estado dentro do LayoutBuilder (por favor 😅)

Eu já vi isso.
Eu já fiz isso.
Eu me arrependo disso.

LayoutBuilder(
  builder: (_, c) {
    setState(() {}); // congratulations, infinite loop activated
    return Container();
  },
);

O Flutter irá reconstruir.
Em seguida, ele chama setState().
Em seguida, reconstrói.
Em seguida, chama setState novamente — você criou um buraco negro.

2. Não espere que o LayoutBuilder corrija elementos pais problemáticos.

O LayoutBuilder não consegue corrigir um widget preso em um contêiner sem limites.

SingleChildScrollView(
  child: LayoutBuilder(
    builder: (_, c) => Container(
      height: c.maxHeight, // 💀 maxHeight is infinite here
    ),
  ),
);

Ele lança o clássico: BoxConstraints força uma altura infinita

O LayoutBuilder não cria restrições definidas magicamente
quando o elemento pai é intencionalmente ilimitado (como em views de rolagem).

3. Não execute cálculos pesados ​​no LayoutBuilder

O LayoutBuilder é reconstruído sempre que suas restrições mudam .
Portanto, se você estiver executando alguma operação custosa dentro dele:

LayoutBuilder(
  builder: (_, c) {
    final result = heavyTask(); // CPU just died
    return Text(result.toString());
  },
);

Elimine trabalhos dispendiosos. O LayoutBuilder serve para decisões de layout, não para ciência espacial.

Compartilhei meus erros — agora é a sua vez.

Qual foi a maneira mais engraçada ou estranha que você usou o LayoutBuilder de forma errada?

 

Please follow and like us:
error0
fb-share-icon
Tweet 20
fb-share-icon20