Flexible es un widget de Flutter que controla cómo un elemento hijo ocupa el espacio disponible en un contenedor Flex. A diferencia de Expanded, Flexible no obliga al hijo a llenar toda el área asignada — el widget hijo puede ser más pequeño y el espacio restante queda vacío. Según la documentación oficial de Flutter (2026), Flexible es necesario en escenarios donde se requiere una distribución flexible del espacio sin estiramiento forzado: botones con ancho mínimo, bloques de texto con tamaño natural y elementos con intrinsic constraints.
Puntos Clave
Flexible es un widget envoltorio que proporciona espacio flexible a un elemento hijo en un contenedor Flex. Flexible, al igual que Expanded, participa en la distribución del espacio libre, pero con una diferencia clave: el hijo de Flexible puede ocupar menos espacio del asignado si su propio tamaño es menor que el espacio disponible.
Flexible utiliza el algoritmo Flex de Flutter para calcular el espacio disponible. Primero, el framework consulta a todos los hijos no flexibles (widgets sin Flexible/Expanded) y calcula su tamaño intrínseco. El espacio restante se divide entre los hijos flexibles proporcionalmente a sus factores flex. Después de la asignación de espacio, Flexible verifica el fit — si es loose, el hijo recibe una restricción de “no más grande de lo asignado”, permitiéndole permanecer pequeño.
Una característica de Flexible: si el widget hijo tiene sus propios tamaños mínimos (por ejemplo, Text con una cadena larga), Flexible asigna el espacio solicitado sin estiramiento forzado. Esto hace que Flexible sea indispensable para elementos cuyo tamaño debe ser determinado por el contenido y no por el contenedor.
En resumen: use Flexible cuando necesite reservar espacio para un elemento pero no forzarlo a estirarse. Esto preserva los tamaños naturales del contenido mientras mantiene una distribución flexible del layout.
FlexFit es una enumeración de dos valores: tight y loose. La elección del fit determina si el widget hijo será estirado forzosamente al tamaño del espacio asignado.
FlexFit.tight: el elemento hijo recibe tight constraints — los tamaños mínimo y máximo son iguales al espacio asignado. El hijo debe ocupar exactamente el espacio que el algoritmo Flex asignó. Si el hijo es más pequeño — se estira. Si es más grande — se encoge. El comportamiento es idéntico a Expanded.
FlexFit.loose: el elemento hijo recibe loose constraints — el tamaño mínimo es 0, el máximo es igual al espacio asignado. El hijo puede tener cualquier tamaño de 0 al máximo. Si el hijo es pequeño (por ejemplo, Text con una cadena corta), ocupa su ancho natural y el espacio restante queda vacío.
En resumen: FlexFit.loose es la opción para bloques de texto y elementos con tamaño natural. FlexFit.tight es para layouts de columna estrictos donde todos los elementos deben tener el mismo ancho o alto.
Flexible y Expanded se ven similares pero resuelven tareas diferentes. Expanded siempre estira al hijo para llenar todo el espacio disponible. Flexible puede dejar espacio vacío alrededor del hijo si el tamaño del contenido es menor que la porción asignada.
Escenario para Flexible: dentro de una Row hay dos botones. El primero — “Comprar” (texto corto), el segundo — “Agregar al Carrito” (texto largo). Con Expanded, ambos botones se estiran al mismo ancho y el texto corto tendrá un padding enorme. Con Flexible, cada botón ocupa el ancho de su texto y el espacio libre queda entre ellos o en los bordes.
Escenario para Expanded: dentro de una Column hay tres tarjetas que deben ocupar la misma altura independientemente del contenido. Expanded divide uniformemente la altura disponible y cada tarjeta se estira al mismo tamaño. Flexible con loose no funcionaría aquí — una tarjeta pequeña seguiría siendo pequeña, rompiendo el diseño uniforme.
En resumen: elija Flexible cuando el contenido determina el tamaño del elemento y el espacio vacío alrededor es aceptable. Elija Expanded cuando todos los elementos deben tener el mismo tamaño independientemente del contenido.
Ejemplo 1 demuestra el uso básico de Flexible con FlexFit.loose en una Row.
Row(
children: [
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.amber,
child: const Text('corto'),
),
),
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.cyan,
child: const Text('texto largo para demo'),
),
),
],
)
En el ejemplo, ambos Flexible usan loose fit. El primer contenedor con texto corto ocupa su ancho natural. El segundo con texto largo — el suyo. Row asigna a cada uno la mitad del ancho disponible, pero loose fit permite que los contenedores sean más pequeños y el espacio libre queda vacío entre ellos.
Ejemplo 2 — comparación de Flexible con Tight y Loose fit en una Column.
Column(
children: [
Flexible(
fit: FlexFit.tight,
child: const Card(
child: ListTile(
title: Text('Tight — altura completa estirada'),
),
),
),
const SizedBox(
height: 8,
),
Flexible(
fit: FlexFit.loose,
child: const Card(
child: ListTile(
title: Text('Loose — altura natural'),
),
),
),
],
)
En la Column, el primer Flexible (tight) estira la Card a la mitad de la altura disponible. El segundo Flexible (loose) — la Card ocupa la altura según su contenido y el espacio restante queda vacío. Visualmente, se puede ver cómo tight llena forzosamente el área, mientras que loose preserva un tamaño compacto.
En resumen: en código de producción, Flexible con loose se usa para campos de formulario, botones y bloques de texto. Flexible con tight es equivalente a Expanded y se usa para distribución uniforme.
Error 1: usar Flexible fuera de un contenedor Flex. Al igual que Expanded, Flexible lanza una LayoutException si no está dentro de Row, Column o Flex. Solución: siempre verifique la cadena de widgets padres.
Error 2: confundir Flexible y Expanded. Los desarrolladores suelen usar Expanded cuando se necesita Flexible con loose fit, y viceversa. Resultado: Expanded estira un elemento con texto corto, creando grandes márgenes vacíos. Solución: si el tamaño del elemento puede ser menor del asignado — use Flexible(fit: FlexFit.loose).
Error 3: factor flex cero. Flexible con flex=0 se comporta como un widget no flexible, lo que puede ser poco intuitivo. El desarrollador espera un comportamiento flexible, pero el elemento ocupa el tamaño mínimo. Solución: flex debe ser ≥1 para una distribución activa del espacio.
Error 4: Flexible dentro de un ScrollView sin restricciones de tamaño. Si Flexible está en una Column dentro de SingleChildScrollView, el contenedor de scroll proporciona espacio infinito y la distribución flex no funciona. Solución: restrinja el tamaño del contenedor de scroll usando SizedBox o ConstrainedBox.
En resumen: Flexible requiere la misma atención al contexto padre que Expanded. La única diferencia es el fit — elíjalo deliberadamente según la tarea.
Preguntas Frecuentes
Expanded es Flexible con un fit=tight fijo. La diferencia es que Expanded tiene una vinculación rígida a llenar todo el espacio disponible, mientras que Flexible puede usar loose fit para preservar el tamaño natural del hijo.
Para botones con diferentes longitudes de texto, use Flexible(fit: FlexFit.loose). Cada botón ocupará el ancho de su contenido y no habrá desproporción entre ellos. Expanded hará que todos los botones tengan el mismo ancho.
Establezca fit: FlexFit.tight — Flexible forzará al hijo a llenar todo el espacio asignado. En este modo, Flexible es completamente idéntico a Expanded en comportamiento.
Sí, si el hijo es más grande que el espacio asignado. Flexible pasa restricciones con un tamaño máximo igual a la porción del contenedor Flex. Si el hijo excede este tamaño, se encoge dentro de las restricciones.
Sí, Flexible funciona con cualquier contenedor Flex, incluyendo Row, Column y el widget base Flex con dirección arbitraria. Flex permite establecer direcciones no estándar a través de mainAxisAlignment y crossAxisAlignment.
Resumen
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.
Lea también