main
md 130 lines 5.2 KB
Rendered Raw
1 ---
2 name: flutter-fix-layout-issues
3 description: Fixes Flutter layout errors (overflows, unbounded constraints) using Dart and Flutter MCP tools. Use when addressing "RenderFlex overflowed", "Vertical viewport was given unbounded height", or similar layout issues.
4 metadata:
5 model: models/gemini-3.1-pro-preview
6 last_modified: Tue, 21 Apr 2026 19:45:59 GMT
7 ---
8 # Resolving Flutter Layout Errors
9
10 ## Contents
11 - [Constraint Violation Diagnostics](#constraint-violation-diagnostics)
12 - [Layout Error Resolution Workflow](#layout-error-resolution-workflow)
13 - [Examples](#examples)
14
15 ## Constraint Violation Diagnostics
16
17 Flutter layout operates on a strict rule: **Constraints go down. Sizes go up. Parent sets position.** Layout errors occur when this negotiation fails, typically due to unbounded constraints or unconstrained children.
18
19 Diagnose layout failures using the following error signatures:
20
21 * **"Vertical viewport was given unbounded height"**: Triggered when a scrollable widget (`ListView`, `GridView`) is placed inside an unconstrained vertical parent (`Column`). The parent provides infinite height, and the child attempts to expand infinitely.
22 * **"An InputDecorator...cannot have an unbounded width"**: Triggered when a `TextField` or `TextFormField` is placed inside an unconstrained horizontal parent (`Row`). The text field attempts to determine its width based on infinite available space.
23 * **"RenderFlex overflowed"**: Triggered when a child of a `Row` or `Column` requests a size larger than the parent's allocated constraints. Visually indicated by yellow and black warning stripes.
24 * **"Incorrect use of ParentData widget"**: Triggered when a `ParentDataWidget` is not a direct descendant of its required ancestor. (e.g., `Expanded` outside a `Flex`, `Positioned` outside a `Stack`).
25 * **"RenderBox was not laid out"**: A cascading side-effect error. Ignore this and look further up the stack trace for the primary constraint violation (usually an unbounded height/width error).
26
27 ## Layout Error Resolution Workflow
28
29 Copy and use this checklist to systematically resolve layout constraint violations.
30
31 ### Task Progress
32 - [ ] Run the application in debug mode to capture the exact layout exception in the console.
33 - [ ] Identify the primary error message (ignore cascading "RenderBox was not laid out" errors).
34 - [ ] Apply the conditional fix based on the specific error type:
35 - **If "Vertical viewport was given unbounded height"**: Wrap the scrollable child (`ListView`, `GridView`) in an `Expanded` widget to consume remaining space, or wrap it in a `SizedBox` to provide an absolute height constraint.
36 - **If "An InputDecorator...cannot have an unbounded width"**: Wrap the `TextField` or `TextFormField` in an `Expanded` or `Flexible` widget.
37 - **If "RenderFlex overflowed"**: Constrain the overflowing child by wrapping it in an `Expanded` widget (to force it to fit) or a `Flexible` widget (to allow it to be smaller than the allocated space).
38 - **If "Incorrect use of ParentData widget"**: Move the `ParentDataWidget` to be a direct child of its required parent. Ensure `Expanded`/`Flexible` are direct children of `Row`/`Column`/`Flex`. Ensure `Positioned` is a direct child of `Stack`.
39 - [ ] Execute Flutter hot reload.
40 - [ ] Run validator -> review errors -> fix: Inspect the UI to verify the red/grey error screen or yellow/black overflow stripes are resolved. If new layout errors appear, repeat the workflow.
41
42 ## Examples
43
44 ### Fixing Unbounded Height (ListView in Column)
45
46 **Input (Error State):**
47 ```dart
48 // Throws "Vertical viewport was given unbounded height"
49 Column(
50 children: <Widget>[
51 const Text('Header'),
52 ListView(
53 children: const <Widget>[
54 ListTile(title: Text('Item 1')),
55 ListTile(title: Text('Item 2')),
56 ],
57 ),
58 ],
59 )
60 ```
61
62 **Output (Resolved State):**
63 ```dart
64 // Wrap ListView in Expanded to constrain its height to the remaining Column space
65 Column(
66 children: <Widget>[
67 const Text('Header'),
68 Expanded(
69 child: ListView(
70 children: const <Widget>[
71 ListTile(title: Text('Item 1')),
72 ListTile(title: Text('Item 2')),
73 ],
74 ),
75 ),
76 ],
77 )
78 ```
79
80 ### Fixing Unbounded Width (TextField in Row)
81
82 **Input (Error State):**
83 ```dart
84 // Throws "An InputDecorator...cannot have an unbounded width"
85 Row(
86 children: [
87 const Icon(Icons.search),
88 TextField(),
89 ],
90 )
91 ```
92
93 **Output (Resolved State):**
94 ```dart
95 // Wrap TextField in Expanded to constrain its width to the remaining Row space
96 Row(
97 children: [
98 const Icon(Icons.search),
99 Expanded(
100 child: TextField(),
101 ),
102 ],
103 )
104 ```
105
106 ### Fixing RenderFlex Overflow
107
108 **Input (Error State):**
109 ```dart
110 // Throws "A RenderFlex overflowed by X pixels on the right"
111 Row(
112 children: [
113 const Icon(Icons.info),
114 const Text('This is a very long text string that will definitely overflow the available screen width and cause a RenderFlex error.'),
115 ],
116 )
117 ```
118
119 **Output (Resolved State):**
120 ```dart
121 // Wrap the Text widget in Expanded to force it to wrap within the available constraints
122 Row(
123 children: [
124 const Icon(Icons.info),
125 Expanded(
126 child: const Text('This is a very long text string that will definitely overflow the available screen width and cause a RenderFlex error.'),
127 ),
128 ],
129 )
130 ```