certmundo.
es‑mx

6 min de lectura

¿Cómo construir layouts y estructurar pantallas en Flutter?

En Flutter, construyes layouts combinando widgets de diseño como Column, Row, Container, Padding y Stack para organizar elementos en pantalla.

Cada pantalla de tu app es un árbol de widgets. Tú decides cómo se acomodan, qué espacio ocupan y cómo responden al contenido.

Los cinco widgets de layout esenciales

Antes de escribir código, necesitas conocer los cinco widgets que usarás en casi todas las pantallas:

Widget ¿Para qué sirve?
Column Apila widgets de arriba hacia abajo
Row Acomoda widgets de izquierda a derecha
Container Caja con tamaño, color, bordes y padding
Padding Agrega espacio alrededor de un widget
Stack Superpone widgets uno encima de otro

Estos cinco son la base. Todo lo demás se construye combinándolos.

Column y Row: el eje principal

Column organiza sus hijos en el eje vertical. Row los organiza en el eje horizontal.

Ambos comparten las mismas propiedades de alineación:

  • mainAxisAlignment: controla el eje principal (vertical en Column, horizontal en Row).
  • crossAxisAlignment: controla el eje cruzado (horizontal en Column, vertical en Row).

Ejemplo 1 — Tarjeta de producto de Mercado Libre

Imagina una tarjeta sencilla con el nombre del producto, el precio y un botón de compra:

Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    const Text(
      'Audífonos Bluetooth',
      style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
    ),
    const SizedBox(height: 8),
    const Text(
      '$850',
      style: TextStyle(fontSize: 16, color: Colors.green),
    ),
    const SizedBox(height: 12),
    ElevatedButton(
      onPressed: () {},
      child: const Text('Agregar al carrito'),
    ),
  ],
)

crossAxisAlignment.start alinea todo al borde izquierdo. SizedBox crea espacio vertical entre elementos.

Ejemplo 2 — Fila de íconos de navegación

Una barra inferior con íconos, como la de Liverpool, usa Row con mainAxisAlignment.spaceAround:

Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: const [
    Icon(Icons.home, size: 28),
    Icon(Icons.search, size: 28),
    Icon(Icons.favorite, size: 28),
    Icon(Icons.person, size: 28),
  ],
)

spaceAround distribuye el espacio libre de forma uniforme entre los íconos.

Container: la caja multipropósito

Container es el widget más flexible para dar forma, color y espaciado a un área de la pantalla.

Sus propiedades más usadas son:

  • width y height: tamaño fijo en píxeles lógicos.
  • color: color de fondo.
  • padding: espacio interior entre el borde y el contenido.
  • margin: espacio exterior alrededor del contenedor.
  • decoration: bordes redondeados, sombras y gradientes.

Ejemplo 3 — Banner de promoción de Bimbo

Container(
  width: double.infinity,
  padding: const EdgeInsets.all(16),
  decoration: BoxDecoration(
    color: Colors.yellow.shade700,
    borderRadius: BorderRadius.circular(12),
  ),
  child: const Text(
    '¡Oferta del día! Pan Blimpy al 2x1',
    style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
    textAlign: TextAlign.center,
  ),
)

double.infinity hace que el contenedor ocupe todo el ancho disponible. BorderRadius.circular(12) redondea las esquinas.

Nota importante: No puedes usar color y decoration al mismo tiempo en un Container. Si usas BoxDecoration, define el color dentro de ella.

Padding: espacio limpio y preciso

Padding agrega espacio interior alrededor de su hijo sin necesidad de un Container.

Es más ligero que Container cuando solo necesitas espacio, sin color ni bordes.

Padding(
  padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
  child: const Text('Bienvenido a FEMSA Digital'),
)

Usa EdgeInsets.symmetric para aplicar el mismo valor en ambos lados del eje. Usa EdgeInsets.only para controlar cada lado por separado.

Comparación: Padding vs Container con padding

Situación Usa
Solo necesitas espacio Padding
Necesitas espacio + color + bordes Container
Necesitas tamaño fijo Container

Stack: capas superpuestas

Stack coloca sus hijos uno encima del otro, como capas. El último hijo en la lista queda al frente.

Es ideal para:

  • Badges de notificación sobre íconos.
  • Textos sobre imágenes.
  • Botones flotantes personalizados.

Ejemplo 4 — Badge de carrito de compras

Stack(
  children: [
    const Icon(Icons.shopping_cart, size: 36),
    Positioned(
      right: 0,
      top: 0,
      child: Container(
        width: 16,
        height: 16,
        decoration: const BoxDecoration(
          color: Colors.red,
          shape: BoxShape.circle,
        ),
        child: const Center(
          child: Text(
            '3',
            style: TextStyle(color: Colors.white, fontSize: 10),
          ),
        ),
      ),
    ),
  ],
)

Positioned es el widget compañero de Stack. Te permite colocar un hijo en una posición exacta usando top, bottom, left y right.

Pantalla completa: combinando todos los widgets

Ahora construye una pantalla real que simula la vista de un producto en una app de Mercado Libre.

import 'package:flutter/material.dart';

class PantallaProducto extends StatelessWidget {
  const PantallaProducto({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Detalle del producto')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Stack(
              children: [
                Container(
                  width: double.infinity,
                  height: 200,
                  decoration: BoxDecoration(
                    color: Colors.grey.shade200,
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: const Icon(Icons.headphones, size: 80, color: Colors.grey),
                ),
                Positioned(
                  top: 8,
                  right: 8,
                  child: Container(
                    padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                    decoration: BoxDecoration(
                      color: Colors.green,
                      borderRadius: BorderRadius.circular(8),
                    ),
                    child: const Text(
                      'En stock',
                      style: TextStyle(color: Colors.white, fontSize: 12),
                    ),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 16),
            const Text(
              'Audífonos Bluetooth Pro',
              style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: const [
                Text(
                  '$1,299',
                  style: TextStyle(fontSize: 24, color: Colors.green, fontWeight: FontWeight.bold),
                ),
                Text(
                  '4.8 ⭐',
                  style: TextStyle(fontSize: 16),
                ),
              ],
            ),
            const SizedBox(height: 16),
            SizedBox(
              width: double.infinity,
              child: ElevatedButton(
                onPressed: () {},
                child: const Text('Comprar ahora'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Este ejemplo combina Padding, Column, Stack, Positioned, Container, Row y SizedBox en una sola pantalla funcional.

Errores comunes

Error 1 — Column sin scroll cuando el contenido es largo. Si agregas muchos widgets en una Column, Flutter lanza un error de overflow. Envuelve la Column en un SingleChildScrollView para hacerla scrolleable.

SingleChildScrollView(
  child: Column(
    children: [ /* muchos widgets */ ],
  ),
)

Error 2 — Usar color y decoration juntos en Container. Esto lanza un error en tiempo de ejecución. Elige uno o el otro. Si necesitas bordes redondeados con color, usa BoxDecoration y define el color dentro de ella.

Error 3 — Olvidar Expanded o Flexible dentro de Row y Column. Si un hijo intenta ocupar más espacio del disponible, Flutter lanza overflow. Usa Expanded para que un hijo llene el espacio restante:

Row(
  children: [
    const Text('Precio:'),
    Expanded(
      child: Text('$18,500', textAlign: TextAlign.end),
    ),
  ],
)

Error 4 — Anidar Column dentro de Column sin restricciones. Una Column dentro de otra Column puede causar problemas de altura infinita. Si necesitas anidar columnas, envuelve la interna en un SizedBox con altura fija o usa Flexible.

Referencia rápida de alineaciones

Valor Comportamiento
MainAxisAlignment.start Agrupa al inicio del eje principal
MainAxisAlignment.center Centra en el eje principal
MainAxisAlignment.end Agrupa al final del eje principal
MainAxisAlignment.spaceBetween Espacio entre elementos, sin margen en extremos
MainAxisAlignment.spaceAround Espacio alrededor de cada elemento
MainAxisAlignment.spaceEvenly Espacio igual entre todos, incluidos los extremos
CrossAxisAlignment.start Alinea al inicio del eje cruzado
CrossAxisAlignment.center Centra en el eje cruzado
CrossAxisAlignment.stretch Estira los hijos para llenar el eje cruzado

Puntos clave para recordar

  • Column y Row controlan la dirección del flujo. Dominarlos es dominar el 80% del layout en Flutter.
  • Container es la herramienta de diseño más flexible: combina tamaño, color, bordes y espacio en un solo widget.
  • Padding es más ligero que Container cuando solo necesitas espacio sin decoración visual.
  • Stack con Positioned te permite superponer capas y colocar elementos en posiciones exactas.
  • Usa Expanded o Flexible para evitar errores de overflow cuando los hijos de una Row o Column ocupan demasiado espacio.

Puntos clave

  • `Column` organiza widgets de forma vertical y `Row` de forma horizontal; ambos usan `mainAxisAlignment` y `crossAxisAlignment` para controlar la alineación.
  • `Container` es el widget multipropósito para tamaño, color, bordes y espacio; nunca uses `color` y `decoration` al mismo tiempo dentro de él.
  • `Padding` es la opción más ligera cuando solo necesitas espacio alrededor de un widget sin decoración adicional.
  • `Stack` superpone widgets en capas y se combina con `Positioned` para colocar elementos en coordenadas exactas dentro de la pantalla.
  • Usa `Expanded` o `SizedBox` para evitar errores de overflow cuando el contenido de una `Column` o `Row` excede el espacio disponible.

Comparte esta lección: