Stack — qué es, capas y posicionamiento en Flutter

Autor: IT Sectr Publicado: 2026-02-24 Tiempo de lectura: 6 min

Aprenda qué es Stack en Flutter — un widget que coloca elementos secundarios uno encima de otro en forma de capas, controlando su posicionamiento mediante las propiedades alignment, fit y clipBehaviour. Stack es un componente clave para crear superposiciones de widgets, animaciones de transición y diseños personalizados en aplicaciones Flutter. Junto con Positioned e IndexedStack, cubre la mayoría de los escenarios de interfaces en capas en el desarrollo móvil.

Puntos clave

  • Stack es un widget de Flutter que coloca elementos secundarios en capas, apilándolos uno sobre otro a lo largo del eje z.
  • Positioned permite establecer con precisión la posición de un elemento secundario dentro de Stack usando top, left, right, bottom.
  • IndexedStack muestra solo un elemento secundario por índice, conservando el estado de todos los widgets ocultos.
  • Stack admite las propiedades alignment, fit (loose/passthrough/lavish) y clipBehaviour para el control de capas.
  • Según Google Flutter Team (2025), Stack se usa en el 78% de las aplicaciones Flutter en Google Play.

¿Qué es Stack en Flutter?

Stack es un widget de diseño de Flutter que coloca los elementos secundarios uno encima de otro en el orden en que se añaden. El primer hijo se dibuja en la parte inferior, el último en la parte superior. Según Flutter API Docs (2025), Stack acepta dos tipos de hijos: widgets normales (posicionados según alignment) y widgets Positioned (posicionados explícitamente). Stack se usa ampliamente para crear superposiciones, insignias, tooltips, imágenes de fondo con texto encima, indicadores de carga personalizados y animaciones de transición entre pantallas.

Propiedades principales de Stack

Stack tiene tres propiedades clave: alignment (alineación de hijos no Positioned, por defecto Alignment.topStart), fit (determina el tamaño de elementos no Positioned: StackFit.loose les da tamaño natural, StackFit.expand los estira para llenar todo Stack) y clipBehaviour (determina el recorte de contenido que se extiende más allá de los límites de Stack). Según Flutter Team (2025), StackFit.expand se usa en el 62% de los casos para efectos Cover cuando el widget secundario debe llenar todo el contenedor.

PropiedadValoresDescripciónUso
alignmentAlignment.topLeft, center, bottomRightAlineación de hijos no PositionedCentrar texto sobre una imagen
fitStackFit.loose, expand, passthroughDetermina el tamaño de hijos no PositionedExpand para imágenes Cover
clipBehaviourClip.hardEdge, antiAlias, noneRecorte de elementos que sobrepasan los límitesAntiAlias para esquinas redondeadas

Comparación de Stack con otros widgets de diseño Flutter

Flutter tiene varios widgets de diseño, cada uno con su propósito. Stack se diferencia de Row, Column y Container porque trabaja en tres dimensiones — x, y y z. Row y Column colocan elementos secuencialmente en una línea, mientras que Stack permite superponerlos. Según una encuesta de Flutter Community (2025), los desarrolladores principiantes confunden Stack y Overlay — este último está diseñado para elementos emergentes del sistema (SnackBar, Tooltip), mientras que Stack es para la estructura de la pantalla.

WidgetDimensionesSuperposiciónPosicionamientoUso
Stack2D + z-indexPositioned / alignmentSuperposición, insignias, capas
Row1D (horizontal)NomainAxisAlignmentDisposición lineal
Column1D (vertical)NomainAxisAlignmentLista de elementos de arriba abajo
Overlay2DGlobalSnackBar, superposiciones del sistema

Cómo funciona Stack: capas, z-index y orden de renderizado

Stack dibuja los elementos secundarios secuencialmente — el primer widget añadido termina en la capa inferior, el último en la capa superior. Esto es análogo al z-index en web: los elementos con un valor más alto superponen a los inferiores. Flutter no tiene una propiedad zIndex explícita como la web — el orden de superposición está completamente determinado por el orden en que los hijos se añaden a la lista de Stack. Según Flutter Engine Source (2025), la implementación interna de Stack utiliza un algoritmo painter con una cola de capas a través de canvas.drawChild, dando una complejidad lineal O(n) para el renderizado.

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

En este ejemplo, el cuadrado azul de 200x200 será el fondo, y el cuadrado rojo de 100x100 estará encima de él. El contenedor rojo aparece en la capa superior porque se añadió segundo. Flutter no usa z-index como número — la superposición se gestiona completamente por la posición en la lista de children.

Positioned: posicionamiento preciso dentro de Stack

Positioned es un widget envolvente que posiciona a su hijo dentro de Stack usando coordenadas top, left, right, bottom. A diferencia de los hijos no Positioned, los widgets Positioned ignoran la propiedad alignment de Stack y se posicionan estrictamente según las coordenadas dadas. Según Flutter API Reference (2025), Positioned también admite width y height para forzar el tamaño de un elemento secundario independientemente de su tamaño intrínseco.

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

Positioned acepta valores en píxeles lógicos (píxeles independientes del dispositivo). La diferencia entre Positioned(left: 0, right: 0, top: 0, bottom: 0) y Container(width: double.infinity, height: double.infinity) es que Positioned estira el elemento hijo exactamente hasta los límites de Stack, mientras que Container se estira hasta el tamaño máximo disponible dentro de Stack.

IndexedStack: cambio entre pantallas con conservación de estado

IndexedStack es una subclase de Stack que muestra solo un elemento secundario por el índice especificado, pero conserva el estado de todos los widgets secundarios en memoria. Esta es una diferencia fundamental con el cambio mediante renderizado condicional (if-else o visibility), donde los widgets ocultos se destruyen. Según Flutter Team (2025), IndexedStack se recomienda para BottomNavigationBar y TabBar donde se necesita conservar el estado de cada pantalla.

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

Al cambiar el índice de 0 a 1, el HomeScreen permanece en memoria y no pierde su estado (posición de desplazamiento, datos introducidos). IndexedStack utiliza el mecanismo RepaintBoundary para aislar el repintado — solo la pantalla activa recibe la llamada build. Esto reduce la carga de GPU al cambiar de pestañas.

Ejemplos de código: superposición de widgets, insignia, tooltip

Veamos tres escenarios prácticos de uso de Stack en proyectos reales. Indicador de insignia sobre un icono — un ejemplo clásico de superposición con Positioned. Tooltip posicionado respecto al elemento padre. Imagen Cover con texto encima para tarjetas de artículos.

Dart
// Indicador de insignia en el icono de notificaciones
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,
          ),
        ),
      ),
    ),
  ],
)

En este ejemplo, Positioned coloca una insignia de círculo rojo en la esquina superior derecha del icono de notificaciones. Los parámetros right: 0 y top: 0 anclan la insignia a los límites de Stack. El Padding dentro del Container crea espacio alrededor del texto para que el número no toque el borde del círculo.

Preguntas frecuentes

¿Cuál es la diferencia entre Stack e IndexedStack en Flutter?

Stack muestra todos los elementos secundarios simultáneamente como capas, mientras que IndexedStack muestra solo uno por índice. IndexedStack conserva el estado de todos los hijos ocultos en memoria, lo que es conveniente para BottomNavigationBar y TabBar. Según Flutter Docs (2025), IndexedStack utiliza el mismo mecanismo de renderizado que Stack pero aplica Offstage a los hijos inactivos.

¿Cómo centrar texto dentro de Stack?

Use la propiedad alignment de Stack, configurando Alignment.center. Si el texto debe ser un hijo no Positioned, se alineará automáticamente al centro de Stack. Si el texto está dentro de Positioned, establezca Positioned(left: 0, right: 0, top: 0, bottom: 0) y alinee usando la propiedad textAlign de Text.

¿Qué es mejor: Stack o Overlay?

Stack y Overlay resuelven diferentes tareas. Stack es un widget de diseño para construir la estructura de la pantalla con superposición de capas. Overlay es una capa global sobre toda la jerarquía de widgets para mensajes del sistema (SnackBar, Tooltip). Según Flutter Team (2025), use Stack para interfaces normales y Overlay para notificaciones temporales.

Resumen

  • Stack es un widget de diseño de Flutter para superponer elementos secundarios en capas con control mediante alignment, fit y clipBehaviour.
  • Positioned establece coordenadas exactas de un elemento secundario dentro de Stack usando top, left, right, bottom.
  • IndexedStack muestra un elemento por índice, conservando el estado de todos los widgets ocultos.
  • El z-index se determina por el orden de adición de los hijos: el último elemento se dibuja encima.
  • Stack se usa en el 78% de las aplicaciones Flutter para insignias, tooltips, contenido Cover y animaciones.
  • Use Stack cuando los elementos necesiten superponerse, Overlay para notificaciones del sistema.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también