🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC(10.09.2026 um 20:11 Uhr)
⚠️ Malware / Trojaner / VirenVorsicht: Android-Malware verschlüsselt Ihre Handys und nimmt heimlich Fotos auf(11.09.2026 um 09:35 Uhr)
🕵️ SicherheitslückenMicrosoft geht endlich eines der nervigsten Probleme von Windows 11 an(11.09.2026 um 11:58 Uhr)
💾 IT Security ToolsSysinternals Suite(11.09.2026 um 12:00 Uhr)
🕵️ SicherheitslückenDefender 0-Day ShieldBreak (CVE-2026-69414) nicht sauber gepatcht - BornCity(11.09.2026 um 12:52 Uhr)
🔧 AI Nachrichten Stealing AI Reasoning Traces(08.09.2026 um 12:20 Uhr)
🔧 AI Nachrichten AIs as Modern Genies(08.09.2026 um 19:12 Uhr)
🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC(10.09.2026 um 20:11 Uhr)
⚠️ Malware / Trojaner / VirenVorsicht: Android-Malware verschlüsselt Ihre Handys und nimmt heimlich Fotos auf(11.09.2026 um 09:35 Uhr)
🕵️ SicherheitslückenMicrosoft geht endlich eines der nervigsten Probleme von Windows 11 an(11.09.2026 um 11:58 Uhr)
💾 IT Security ToolsSysinternals Suite(11.09.2026 um 12:00 Uhr)
🕵️ SicherheitslückenDefender 0-Day ShieldBreak (CVE-2026-69414) nicht sauber gepatcht - BornCity(11.09.2026 um 12:52 Uhr)
🔧 AI Nachrichten Stealing AI Reasoning Traces(08.09.2026 um 12:20 Uhr)
🔧 AI Nachrichten AIs as Modern Genies(08.09.2026 um 19:12 Uhr)

🔧 Programmierung 🕛 vor 2 Monaten 9 Min Lesezeit
0

Flutter Layout — Complete Guide

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Flutter Layout — Complete Guide






1. The Core Mental Model



Flutter layout runs on one rule, repeated at every level of the widget tree:




Constraints go down. Sizes go up. Position is set by the parent.





  • A parent passes constraints (min/max width, min/max height) down to its child.

  • The child looks at those constraints, decides its own size (within them), and passes that size back up.

  • The parent then decides where to place the child (its position), based on its own layout logic (Row, Column, Stack, etc.).


  • A widget cannot know or decide its own position — only its size, and only within the constraints given.


  • A parent cannot just tell a child "be this exact size" without constraints — it does so by passing tight constraints.



This single-pass, top-down/bottom-up system is why Flutter layout is fast (no repeated relayout passes like some browser engines) but also why certain patterns (like "make me the same size as my sibling") require special widgets to solve.






Constraints (BoxConstraints)






CODE
BoxConstraints(
minWidth: 0, maxWidth: 300,
minHeight: 0, maxHeight: 150,
)








  • Tight constraints: min == max (e.g., BoxConstraints.tight(Size(100,100))). The child has no choice — it must be that exact size.


  • Loose constraints: min is 0, max is some value. The child can be anywhere from 0 up to that max.


  • Unbounded constraints: max is double.infinity. This is where the infamous "RenderBox was not laid out" or "BoxConstraints forces an infinite width" errors come from — usually caused by putting an unconstrained widget (like ListView or Column) inside another unconstrained widget (like inside a Row without Expanded, or inside a scrollable without a fixed height).









2. Everything Is a Widget



Widgets are configuration — immutable blueprints. Three widget trees exist under the hood:





  1. Widget tree — what you write (immutable, cheap to rebuild).


  2. Element tree — the "live" instantiation, persists across rebuilds, manages state.


  3. RenderObject tree — does the actual layout, painting, and hit-testing math.



For layout purposes, what matters is the RenderObject tree — every widget that affects layout ultimately creates or configures a RenderBox that participates in the constraints-down/sizes-up protocol.









3. Single-Child Layout Widgets



These take one child and adjust size/position/constraints.






Container



The Swiss-army-knife. Combines padding, margin, alignment, decoration, and constraints.




CODE
Container(
width: 200,
height: 100,
padding: EdgeInsets.all(16),
margin: EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
),
child: Text('Hello'),
)






Behavior depends on what's set:




  • If width/height given → tightens constraints to that size (if the parent allows).

  • If no size given but has a child → sizes to fit the child (adds padding).

  • If no size and no child → tries to expand to fill available space.






Padding



Adds space around a child, shrinking the constraints passed down by the insets.




CODE
Padding(padding: EdgeInsets.all(16), child: Text('Hi'))









Center / Align



Align positions a child within itself according to Alignment (e.g., Alignment.topRight), and by default sizes itself to fill available space. Center is just Align with Alignment.center.




CODE
Align(alignment: Alignment.bottomRight, child: Icon(Icons.star))









SizedBox



Forces exact width/height (tight constraints), or use SizedBox.expand() / SizedBox.shrink(). Also commonly used as a spacer:




CODE
SizedBox(height: 20) // vertical gap between widgets









ConstrainedBox / UnconstrainedBox



ConstrainedBox adds additional constraints (it intersects with what the parent gives, doesn't override).




CODE
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100, maxWidth: 300),
child: Text('Flexible width text'),
)









FittedBox



Scales/fits a child within itself using BoxFit (cover, contain, fill, etc.) — useful for text or images that must shrink to fit.






AspectRatio



Forces the child into a specific width/height ratio, respecting incoming constraints as much as possible.






IntrinsicWidth / IntrinsicHeight



Sizes a child based on its "intrinsic" (natural/preferred) dimensions rather than the parent's constraints. Expensive (extra layout passes) — use sparingly, e.g., making buttons in a Row all match the height of the tallest one.






Transform



Applies a matrix transform (rotate, scale, skew, translate) at paint time — does not affect layout/constraints, only how it's drawn (so it can visually overflow its bounds without affecting siblings).









4. Multi-Child Layout Widgets






Row & Column (Flex)



Both are Flex under the hood — Row lays out horizontally, Column vertically.





  • Main axis: the direction of layout (horizontal for Row, vertical for Column).


  • Cross axis: perpendicular to that.




CODE
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [Widget1(), Widget2(), Widget3()],
)






MainAxisAlignment (spacing along main axis):

start, end, center, spaceBetween, spaceAround, spaceEvenly



CrossAxisAlignment (alignment along cross axis):

start, end, center, stretch, baseline



MainAxisSize:





  • max (default) — Row/Column takes all available space on the main axis.


  • min — shrinks to fit just its children.



Key gotcha: A Row has unbounded width if placed inside something that gives infinite width (like a horizontally scrolling parent without explicit sizes) — this causes overflow errors. Non-flexible children in a Row/Column must fit within the available space, or you get the classic yellow-and-black striped overflow warning.





Expanded & Flexible



Used only inside Row/Column/Flex to control how children share leftover space along the main axis.




CODE
Row(
children: [
Expanded(flex: 2, child: Container(color: Colors.red)),
Expanded(flex: 1, child: Container(color: Colors.blue)),
],
)








  • Expanded = Flexible with FlexFit.tight — the child is forced to fill its share of space exactly.


  • Flexible with FlexFit.loose (default) — the child can be up to its share of space, but isn't forced to fill it.


  • flex — the relative weight (default 1) determining how leftover space is divided among flexible children.



Without Expanded/Flexible, children in a Row/Column take only their natural (intrinsic) size — if that combined size exceeds available space, you get an overflow.






Stack & Positioned



Layers children on top of each other (z-axis), like absolute positioning in CSS.




CODE
Stack(
alignment: Alignment.center,
fit: StackFit.loose,
children: [
Container(color: Colors.grey), // sized by non-positioned children or Stack itself
Positioned(top: 10, right: 10, child: Icon(Icons.close)),
Positioned.fill(child: Center(child: Text('Overlay'))),
],
)







  • Children without Positioned are laid out first ("non-positioned"), sized according to fit (loose = as small as possible, expand = fill the Stack) and placed per alignment.


  • Positioned children are placed using top/bottom/left/right/width/height relative to the Stack's own bounds — these are not in the constraints-down flow the same way; the Stack determines its own size from non-positioned children (or fills available space if given tight constraints), then positions the Positioned ones absolutely within that.






Wrap



Like Row/Column, but overflows onto new lines/columns when out of space, instead of clipping/erroring.




CODE
Wrap(
spacing: 8, runSpacing: 4,
children: List.generate(10, (i) => Chip(label: Text('Item $i'))),
)









ListView, GridView, and other scrollables



These are unbounded on the scroll axis internally — they build children lazily (ListView.builder) and give each child unbounded space along the scroll direction but bounded on the cross axis. This is why putting a ListView inside a Column without wrapping it in Expanded or giving it a fixed height throws a layout error (a Column gives unbounded height to its children by default when it's inside something scrollable, and ListView also wants unbounded height — two unbounded things fighting).




CODE
Column(
children: [
Text('Header'),
Expanded(child: ListView(children: [...])), // now ListView gets bounded height
],
)






GridView works similarly but lays children in a 2D grid — controlled via gridDelegate:




CODE
GridView.count(crossAxisCount: 3, children: [...])
// or
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (context, i) => Card(),
itemCount: 20,
)









CustomMultiChildLayout / CustomSingleChildLayout



Escape hatches for fully custom layout logic — you implement a LayoutDelegate/SingleChildLayoutDelegate and manually compute constraints/positions for each labeled child. Rarely needed unless building complex custom widgets.









5. Slivers (for scroll-heavy layouts)



CustomScrollView + slivers give fine control over scroll behavior — collapsing app bars, mixed lists/grids, sticky headers.




CODE
CustomScrollView(
slivers: [
SliverAppBar(expandedHeight: 200, pinned: true, flexibleSpace: FlexibleSpaceBar(title: Text('Title'))),
SliverList(delegate: SliverChildBuilderDelegate((c, i) => ListTile(title: Text('$i')))),
SliverGrid(gridDelegate: ..., delegate: ...),
],
)






Slivers use a different protocol than boxes (SliverConstraints/SliverGeometry instead of BoxConstraints/Size), because they need to describe how much of themselves is currently visible within a scrolling viewport, not just a fixed size.









6. Responsive & Adaptive Layout






MediaQuery



Gives you the size/properties of the whole screen (or nearest ancestor MediaQuery):




CODE
final size = MediaQuery.of(context).size;
final isTablet = size.width > 600;






Rebuilds the widget whenever the queried value changes (e.g., rotation), so avoid over-querying deep in performance-critical trees.






LayoutBuilder



Gives you the incoming constraints at that point in the tree (more precise than MediaQuery, which is screen-wide) — essential for building widgets that adapt to their parent's size, not the whole screen:




CODE
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 600) {
return WideLayout();
}
return NarrowLayout();
},
)









OrientationBuilder



Rebuilds based on portrait/landscape orientation specifically.






FractionallySizedBox



Sizes a child as a fraction of the parent's available space:




CODE
FractionallySizedBox(widthFactor: 0.8, child: Text('80% width'))












7. Text Layout Specifics



Text has its own layout quirks:





  • Text wraps automatically within its constrained width; overflow: TextOverflow.ellipsis combined with maxLines prevents overflow errors.


  • softWrap, textAlign, textScaleFactor (deprecated in favor of TextScaler) all affect how much space text actually needs.

  • Wrapping Text in Expanded or Flexible inside a Row is often required, otherwise a long string can force the Row to overflow horizontally.









8. Common Errors & How to Read Them

































Error Typical Cause Fix
"RenderFlex overflowed by X pixels" Children's natural size exceeds Row/Column space Wrap overflowing child in Expanded/Flexible, or use Wrap, or scroll
"BoxConstraints forces an infinite width/height" Unbounded widget (ListView, Column) inside another unbounded context Give explicit size, or wrap in Expanded/SizedBox/ConstrainedBox
"Vertical viewport was given unbounded height"
ListView/Column with scrollable inside another scrollable/Column without constraints
Wrap the scrollable in Expanded or set shrinkWrap: true (careful: perf cost)
"A RenderFlex overflowed" only in debug (yellow/black stripes) Same as above — it's a visual warning, not a crash Same fixes


Debugging tools:





  • debugPaintSizeEnabled = true — visualizes all box boundaries.

  • Flutter DevTools Layout Explorer — inspect constraints/flex factors visually per widget.


  • Widget Inspector — click any widget on screen to see its render tree info.









9. Performance Notes




  • Layout is generally a single pass per frame (parent asks child to lay out once) — but widgets like IntrinsicWidth/IntrinsicHeight force extra passes and are more expensive.

  • Rebuilds (setState) don't necessarily mean relayout — Flutter only recomputes layout/paint for subtrees whose constraints or geometry actually changed (RenderObject.markNeedsLayout is only called when necessary).

  • Keys (ValueKey, GlobalKey) matter for preserving state and identity across rebuilds when list order or widget type changes, but they don't directly affect the layout algorithm itself.









10. Quick Reference Cheat Sheet





  • Center something: Center or Align


  • Fixed size: SizedBox


  • Extra space around: Padding


  • Share space along a Row/Column: Expanded / Flexible


  • Overlap widgets: Stack + Positioned


  • Wrap onto new lines: Wrap


  • Scrollable list: ListView.builder


  • Adapt to parent size: LayoutBuilder


  • Adapt to screen size: MediaQuery


  • Percentage sizing: FractionallySizedBox


  • Force aspect ratio: AspectRatio


  • Fit content to box (image/text): FittedBox

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Stealing AI Reasoning Traces
1 Quelle
AIs as Modern Genies
1 Quelle
Bitcoin: KI-Hacker räumen Millionen ab! Wird Künstliche Intelligenz zum Problem? - ftd.de
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Flutter Layout — Complete Guide

Thematisch verwandte Begriffe: Flutter, Layout, Complete, Guide · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...