Flutter Layout Audit

NutriTrack Pro — Corrección de Errores de Layout

Diagnóstico técnico y código corregido para las 4 pantallas con errores de restricciones de layout

Flutter 3.22 · Dart 3.4 App: NutriTrack Pro Preparado por CULTIVA IA Junio 2026
4
Errores detectados
4
Errores resueltos
4
Pantallas afectadas
~1h
Tiempo estimado fix

Flujo de trabajo aplicado

✅ Checklist de resolución de constraints — Flutter Layout Error Workflow
Ejecutar en
debug mode
Identificar error
primario
Aplicar fix
condicional
Hot reload
+ verificar
Sin overflow
stripes

Diagnóstico y correcciones por pantalla

1
Vertical viewport was given unbounded height
Pantalla: Home · Componente: RecetasDelDiaWidget
✓ Resuelto
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═══════════ The following assertion was thrown during layout: Vertical viewport was given unbounded height. Viewports expand in the scrolling direction to fill their container. In this case, a vertical viewport was given an unlimited amount of vertical space in which to expand. This situation typically happens when a scrollable widget is nested inside another scrollable widget. Consider using a SizedBox or Expanded widget to constrain the height.
Diagnóstico

El ListView de recetas diarias está como hijo directo de un Column sin altura acotada. Flutter intenta dar al ListView altura infinita → excepción. Regla: Constraints go down. Sizes go up. La Column no tiene límite para transmitir al ListView.

✗ Antes — Estado con error
Column( children: [ HeaderSaludo(), ListView.builder( // ← sin constraints itemCount: recetas.length, itemBuilder: (ctx, i) => RecetaTile(receta: recetas[i]), ), ], )
✓ Después — Corregido
Column( children: [ HeaderSaludo(), Expanded( // ← acota la altura child: ListView.builder( itemCount: recetas.length, itemBuilder: (ctx, i) => RecetaTile(receta: recetas[i]), ), ), ], )
2
An InputDecorator cannot have an unbounded width
Pantalla: Búsqueda · Componente: BarraBusquedaWidget
✓ Resuelto
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═══════════ An InputDecorator, which is typically created by a TextField, cannot have an unbounded width. This happens when the parent widget does not provide a finite width constraint. For example, if the InputDecorator is contained within a Row widget, then the Row should be constrained, e.g. using the Expanded widget. Consider wrapping the TextField in an Expanded or SizedBox widget.
Diagnóstico

El TextField de búsqueda está dentro de un Row junto a un Icon. La Row no da anchura definida al TextField, que intenta calcularla en base a espacio infinito. Solución: envolver en Expanded para que ocupe el espacio restante de la Row.

✗ Antes — Estado con error
Row( children: [ Icon(Icons.search, color: Colors.grey), TextField( // ← ancho no acotado hintText: 'Buscar receta...', controller: searchCtrl, ), ], )
✓ Después — Corregido
Row( children: [ Icon(Icons.search, color: Colors.grey), Expanded( // ← acota el ancho child: TextField( hintText: 'Buscar receta...', controller: searchCtrl, ), ), ], )
3
RenderFlex overflowed by 42 pixels on the right
Pantalla: Perfil · Componente: TarjetaUsuarioWidget
✓ Resuelto
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═══════════ A RenderFlex overflowed by 42.0 pixels on the right. The relevant error-causing widget was: Row lib/screens/profile/tarjeta_usuario_widget.dart:24 The overflowing RenderFlex has an orientation of Axis.horizontal. Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the RenderFlex to fit within the available space instead of being sized to their intrinsic dimensions.
Diagnóstico

La tarjeta de perfil muestra nombre del usuario + badge de nivel en una Row. Nombres largos como "María Fernández-Castillo" exceden el ancho disponible. El Text no tiene instrucción de flex → desborda con las rayas amarillas/negras características. Solución: Expanded en el Text del nombre.

✗ Antes — Estado con error
Row( children: [ CircleAvatar(radius: 28, ...), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(usuario.nombre), // ← overflow Text(usuario.email), ], ), NivelBadge(nivel: usuario.nivel), ], )
✓ Después — Corregido
Row( children: [ CircleAvatar(radius: 28, ...), Expanded( // ← flex en la Column child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(usuario.nombre, overflow: TextOverflow.ellipsis), Text(usuario.email), ], ), ), NivelBadge(nivel: usuario.nivel), ], )
4
Incorrect use of ParentData widget (Expanded)
Pantalla: Planes · Componente: PlanNutricionalCard
✓ Resuelto
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═══════════ Incorrect use of ParentData widget. The Expanded widget must be a descendant of a Row, Column, or Flex widget. The ownership chain for the parent of the offending Expanded widget was: Container ← Padding ← Container ← ... ← PlanNutricionalCard Ensure that Expanded and Flexible widgets are direct children of Row, Column, or Flex widgets.
Diagnóstico

En la pantalla de Planes, un Expanded fue colocado dentro de un Container (para añadir padding), en lugar de ser hijo directo de la Row/Column. Expanded es un ParentDataWidget que solo funciona como descendiente directo de un Flex widget. Solución: reestructurar para que el Expanded sea hijo directo del Row.

✗ Antes — Estado con error
Row( children: [ PlanIcon(tipo: plan.tipo), Container( // ← wrap incorrecto padding: EdgeInsets.only(left: 12), child: Expanded( // ← Error aquí child: PlanInfoColumn(plan: plan), ), ), ], )
✓ Después — Corregido
Row( children: [ PlanIcon(tipo: plan.tipo), Expanded( // ← hijo directo de Row child: Padding( // padding adentro padding: EdgeInsets.only(left: 12), child: PlanInfoColumn(plan: plan), ), ), ], )

Resumen de impacto por pantalla

# Pantalla Error Flutter Severidad Fix aplicado Estado
1 Home Vertical viewport unbounded height Crítico Envolver ListView en Expanded
2 Búsqueda InputDecorator unbounded width Crítico Envolver TextField en Expanded
3 Perfil RenderFlex overflowed 42px Alto Expanded en Column + TextOverflow.ellipsis
4 Planes Incorrect use of ParentData Alto Mover Expanded a hijo directo de Row