On this page23 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. Column — Top to Bottom
  5. 2. Row — Left to Right
  6. 3. Main Axis and Cross Axis
  7. 4. crossAxisAlignment
  8. 5. Gaps: spacing and SizedBox
  9. 6. mainAxisSize
  10. 7. Expanded — Take the Rest
  11. 8. flex — Share the Space
  12. 9. Spacer
  13. 10. The Overflow Error
  14. 11. A Real-World Example
  15. Code Examples
  16. Common Beginner Mistakes
  17. Best Practices
  18. Mini Challenge
  19. Practice Questions
  20. Practice Answers
  21. Quick Revision
  22. Key Takeaways
  23. What's Next?

Lecture 004 — Row & Column

Category2 — Layout Widgets
Lecture004 of 009
Estimated video length20 min
TargetFlutter 3.44 · Dart 3.12
LevelBeginner

Until now every screen held one widget, and we hid multi-line text behind \n. Row and Column take a whole list of children and lay them out side by side or top to bottom — the way almost every real screen is built.

Contents

Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways

Every screenshot and error message in this lecture is real. Each app was run on Flutter 3.44, and each error was produced by the code shown.


Prerequisites

Students should already understand, from Lectures 001–003:

  • screens built from Scaffold, AppBar and a StatelessWidget
  • Padding, SizedBox, Align and the "constraints go down, sizes go up" rule
  • Container, BoxDecoration and TextStyle
  • Dart Lists from the Dart course: [a, b, c]

Connection With Previous Lectures

In Lecture 003 Zayan's bank card showed his name and balance with a single Text and \n. That trick breaks down fast: the two lines cannot have different styles, and we could never put an avatar next to the name. A screen is really a stack of rows — a header, a line of details, a total — and each row is a line of pieces. We need widgets that hold many children.


Learning Objectives

By the end of this lecture you will be able to:

  • Lay out children vertically with Column and horizontally with Row
  • Explain the main axis and the cross axis of each
  • Position children with mainAxisAlignment and crossAxisAlignment
  • Add gaps with spacing or SizedBox, and shrink a Column with mainAxisSize
  • Share space with Expanded, flex and Spacer
  • Recognize the overflow stripes and fix them
  • Nest Rows inside Columns to build real layouts

1. Column — Top to Bottom

Column takes a children list and places them one below the other:

dart
body: const Column(children: [Text('Ali'), Text('Sara'), Text('Zayan')]),
The names Ali, Sara and Zayan on three lines at the top-left
A Column of three Text widgets

children is an ordinary Dart List<Widget> — square brackets, commas between items, and a trailing comma at the end.

Analogy — a Column is a stack of books on a shelf, top to bottom; a Row is the same books standing side by side. The shelf decides where the books go; each book only decides its own size.

Notice the names are centered under each other but sit at the left of the screen. A Column is only as wide as its widest child — "Zayan" — and centers the others inside that width.


2. Row — Left to Right

Row works the same way, horizontally:

dart
body: Row(
  children: [
    Container(
      width: 80,
      height: 80,
      color: Colors.red.shade200,
      alignment: Alignment.center,
      child: const Text('A'),
    ),
    Container(
      width: 80,
      height: 80,
      color: Colors.green.shade200,
      alignment: Alignment.center,
      child: const Text('B'),
    ),
    Container(
      width: 80,
      height: 80,
      color: Colors.blue.shade200,
      alignment: Alignment.center,
      child: const Text('C'),
    ),
  ],
),
Three 80-pixel squares A, B and C touching each other at the top-left
A Row of three Containers

3. Main Axis and Cross Axis

Every Row and Column has two directions:

Main axis (the direction children follow)Cross axis (the other direction)
Columnvertical ↓horizontal →
Rowhorizontal →vertical ↓

mainAxisAlignment decides where children go along the main axis:

dart
body: Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Container(
      width: 80,
      height: 80,
      color: Colors.red.shade200,
      alignment: Alignment.center,
      child: const Text('A'),
    ),
    Container(
      width: 80,
      height: 80,
      color: Colors.green.shade200,
      alignment: Alignment.center,
      child: const Text('B'),
    ),
    Container(
      width: 80,
      height: 80,
      color: Colors.blue.shade200,
      alignment: Alignment.center,
      child: const Text('C'),
    ),
  ],
),
The three squares spread across the width with equal gaps
MainAxisAlignment.spaceEvenly

There are six options. Here they are all at once, each on a grey Row:

Six grey strips showing start, center, end, spaceBetween, spaceAround and spaceEvenly
The six MainAxisAlignment values
  • start, center, end — push the group to one end or the middle.
  • spaceBetween — first and last touch the edges; the free space goes between.
  • spaceAround — every child gets equal space on both sides (so the outer gaps are half size).
  • spaceEvenly — every gap, including the outer ones, is equal.

4. crossAxisAlignment

crossAxisAlignment places children across the main axis. In this Row the boxes have different heights:

dart
body: Container(
  height: 160,
  color: Colors.grey.shade200,
  child: Row(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      Container(
        width: 80,
        height: 40,
        color: Colors.red.shade200,
        alignment: Alignment.center,
        child: const Text('A'),
      ),
      Container(
        width: 80,
        height: 80,
        color: Colors.green.shade200,
        alignment: Alignment.center,
        child: const Text('B'),
      ),
      Container(
        width: 80,
        height: 120,
        color: Colors.blue.shade200,
        alignment: Alignment.center,
        child: const Text('C'),
      ),
    ],
  ),
),
Boxes of heights 40, 80 and 120 all lined up along the top
CrossAxisAlignment.start

start lines them up at the top; center (the default) through their middles; end along the bottom. The fourth option, stretch, makes every child as big as the cross axis allows:

dart
body: Padding(
  padding: const EdgeInsets.all(16),
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      Container(height: 48, color: Colors.indigo.shade100),
      const SizedBox(height: 12),
      Container(height: 48, color: Colors.indigo.shade200),
      const SizedBox(height: 12),
      Container(height: 48, color: Colors.indigo.shade300),
    ],
  ),
),
Three full-width indigo bars stacked with gaps
CrossAxisAlignment.stretch in a Column

None of these Containers has a width — stretch gave them the full width.


5. Gaps: spacing and SizedBox

Row and Column have a spacing parameter that puts the same gap between every pair of children:

dart
body: Padding(
  padding: const EdgeInsets.all(16),
  child: Row(
    spacing: 16,
    children: [
      Container(
        width: 80,
        height: 80,
        color: Colors.red.shade200,
        alignment: Alignment.center,
        child: const Text('A'),
      ),
      Container(
        width: 80,
        height: 80,
        color: Colors.green.shade200,
        alignment: Alignment.center,
        child: const Text('B'),
      ),
      Container(
        width: 80,
        height: 80,
        color: Colors.blue.shade200,
        alignment: Alignment.center,
        child: const Text('C'),
      ),
    ],
  ),
),
The three squares with 16-pixel gaps
spacing: 16

When gaps should differ, put a SizedBox(height: …) (in a Column) or SizedBox(width: …) (in a Row) between the children, as in the stretch example above.


6. mainAxisSize

By default a Column is as tall as it is allowed to be — that is how MainAxisAlignment.end could push children to the bottom. MainAxisSize.min makes it only as tall as its children:

dart
body: Center(
  child: Container(
    padding: const EdgeInsets.all(16),
    color: Colors.amber.shade100,
    child: const Column(
      mainAxisSize: MainAxisSize.min,
      children: [Text('Only as tall'), Text('as its children')],
    ),
  ),
),
A small amber box in the center that just fits two lines of text
MainAxisSize.min

Without mainAxisSize: MainAxisSize.min, the amber Container would stretch from the top of the body to the bottom.


7. Expanded — Take the Rest

Expanded makes a child fill the space left over after the other children are laid out:

dart
body: Padding(
  padding: const EdgeInsets.all(16),
  child: Row(
    children: [
      Container(width: 80, height: 80, color: Colors.red.shade200),
      Expanded(
        child: Container(height: 80, color: Colors.green.shade200),
      ),
      Container(width: 80, height: 80, color: Colors.blue.shade200),
    ],
  ),
),
A red and a blue 80-pixel square at the ends and a green box filling the gap
The green Container is Expanded

The green Container has no width — Expanded gives it everything the two fixed boxes did not use. That is how a screen adapts to every phone width.


8. flex — Share the Space

When several children are Expanded, they share the leftover space. flex sets each one's share:

dart
body: Padding(
  padding: const EdgeInsets.all(16),
  child: Row(
    children: [
      Expanded(
        flex: 2,
        child: Container(
          height: 80,
          color: Colors.red.shade200,
          alignment: Alignment.center,
          child: const Text('flex: 2'),
        ),
      ),
      Expanded(
        child: Container(
          height: 80,
          color: Colors.blue.shade200,
          alignment: Alignment.center,
          child: const Text('flex: 1'),
        ),
      ),
    ],
  ),
),
A red box twice as wide as the blue box next to it
flex: 2 and flex: 1

The space is split into 2 + 1 = 3 parts; the red box gets 2 of them. flex defaults to 1, so three plain Expanded children get equal thirds.


9. Spacer

Spacer() is an empty Expanded — it pushes its neighbors apart:

dart
body: const Padding(
  padding: EdgeInsets.all(16),
  child: Row(
    children: [
      Text('Total'),
      Spacer(),
      Text('Rs. 750', style: TextStyle(fontWeight: FontWeight.bold)),
    ],
  ),
),
Total at the left and a bold Rs. 750 at the right
Spacer between two Texts

10. The Overflow Error

What if the children need more space than the Row has?

dart
body: Row(
  children: [
    Container(width: 60, height: 60, color: Colors.orange),
    const Text(
      'Sara ordered three notebooks, two pens and a very large geometry box',
    ),
  ],
),
The text cut off at the right edge with yellow and black stripes
A RenderFlex overflow
output
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞══════════════════════
The following assertion was thrown during layout:
A RenderFlex overflowed by 154 pixels on the right.

A Row gives every non-Expanded child as much width as it asks for, and a long Text asks for its full one-line width. The yellow and black stripes mark the edge that overflowed (they only appear in debug builds — in a release build the text is simply cut off).

The fix: wrap the Text in Expanded. Now it receives only the leftover width and wraps onto more lines:

dart
body: Row(
  children: [
    Container(width: 60, height: 60, color: Colors.orange),
    const SizedBox(width: 12),
    const Expanded(
      child: Text(
        'Sara ordered three notebooks, two pens and a very large geometry box',
      ),
    ),
  ],
),
The text wrapped onto two lines next to the orange box
Expanded fixes the overflow

11. A Real-World Example

Ali's result card: a Column of Rows inside a decorated Container. It uses an avatar circle, Expanded, spaceBetween, stretch, spacing and MainAxisSize.min.

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.blue),
      home: const ResultScreen(),
    );
  }
}

class ResultScreen extends StatelessWidget {
  const ResultScreen({super.key});

  @override
  Widget build(BuildContext context) {
    String name = 'Ali';
    int math = 80;
    int science = 75;
    int english = 85;
    int total = math + science + english;

    return Scaffold(
      appBar: AppBar(title: const Text('Result')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Container(
          padding: const EdgeInsets.all(20),
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(16),
            boxShadow: const [
              BoxShadow(
                color: Colors.black12,
                blurRadius: 10,
                offset: Offset(0, 4),
              ),
            ],
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            spacing: 12,
            children: [
              Row(
                children: [
                  Container(
                    width: 48,
                    height: 48,
                    alignment: Alignment.center,
                    decoration: const BoxDecoration(
                      color: Colors.blue,
                      shape: BoxShape.circle,
                    ),
                    child: Text(
                      name[0],
                      style: const TextStyle(color: Colors.white, fontSize: 22),
                    ),
                  ),
                  const SizedBox(width: 12),
                  Expanded(
                    child: Text(
                      name,
                      style: const TextStyle(
                        fontSize: 22,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                  const Text('Grade A', style: TextStyle(color: Colors.green)),
                ],
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [const Text('Math'), Text('$math')],
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [const Text('Science'), Text('$science')],
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [const Text('English'), Text('$english')],
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  const Text(
                    'Total',
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                  Text(
                    '$total / 300',
                    style: const TextStyle(fontWeight: FontWeight.bold),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}
A white card with a blue A avatar, Ali, Grade A, then Math 80, Science 75, English 85 and Total 240 / 300
Ali's result card

name[0] is the first character of the string, from the Dart course — 'A'. Each subject line is a Row with spaceBetween, so the label sits left and the number right. stretch makes every Row full width; without it the rows would shrink to their content and spaceBetween would have no space to spread.


Code Examples

Example 1 — A Centered Title Block

mainAxisAlignment: MainAxisAlignment.center centers vertically; the surrounding Center centers horizontally.

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Example 1')),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Welcome', style: TextStyle(fontSize: 32)),
            SizedBox(height: 8),
            Text('to the Essential Widgets course'),
          ],
        ),
      ),
    );
  }
}
Welcome in large text with a smaller line under it, in the middle of the screen
Example 1

Example 2 — Bottom-Right Staircase

A Column is only as wide as its widest child, so crossAxisAlignment.end alone would line the bars up inside a 240-pixel column at the left. SizedBox(width: double.infinity) makes the column full width first. double.infinity means "as big as allowed".

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Example 2')),
      body: SizedBox(
        width: double.infinity,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            Container(width: 120, height: 40, color: Colors.teal.shade100),
            Container(width: 180, height: 40, color: Colors.teal.shade200),
            Container(width: 240, height: 40, color: Colors.teal.shade300),
          ],
        ),
      ),
    );
  }
}
Three teal bars of growing width stacked at the bottom-right
Example 2

Example 3 — Three Equal Columns

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Example 3')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          spacing: 8,
          children: [
            Expanded(child: Container(height: 60, color: Colors.red.shade200)),
            Expanded(
              child: Container(height: 60, color: Colors.green.shade200),
            ),
            Expanded(child: Container(height: 60, color: Colors.blue.shade200)),
          ],
        ),
      ),
    );
  }
}
Three equal-width colored boxes with gaps
Example 3

Example 4 — Shopping Cart Lines

Expanded on the item name pushes the quantities and prices into a neat right-hand column.

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.green),
      home: const CartScreen(),
    );
  }
}

class CartScreen extends StatelessWidget {
  const CartScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Cart')),
      body: const Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          spacing: 12,
          children: [
            Row(
              children: [
                Expanded(child: Text('Notebook')),
                Text('3 × 120'),
                SizedBox(width: 16),
                Text('Rs. 360'),
              ],
            ),
            Row(
              children: [
                Expanded(child: Text('Pen')),
                Text('5 × 30'),
                SizedBox(width: 16),
                Text('Rs. 150'),
              ],
            ),
            Row(
              children: [
                Expanded(
                  child: Text(
                    'Total',
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                ),
                Text('Rs. 510', style: TextStyle(fontWeight: FontWeight.bold)),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
Notebook 3 × 120 Rs. 360, Pen 5 × 30 Rs. 150, and a bold Total Rs. 510
Example 4

Example 5 — Bank Overview

A full-width balance card above a Row of two equal Expanded boxes.

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const BankScreen(),
    );
  }
}

class BankScreen extends StatelessWidget {
  const BankScreen({super.key});

  @override
  Widget build(BuildContext context) {
    int income = 40000;
    int expense = 15000;

    return Scaffold(
      appBar: AppBar(title: const Text('Bank')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          spacing: 16,
          children: [
            Container(
              width: double.infinity,
              padding: const EdgeInsets.all(24),
              decoration: BoxDecoration(
                color: Colors.indigo,
                borderRadius: BorderRadius.circular(16),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    'Balance',
                    style: TextStyle(color: Colors.white70),
                  ),
                  Text(
                    'Rs. ${income - expense}',
                    style: const TextStyle(
                      color: Colors.white,
                      fontSize: 30,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
            ),
            Row(
              spacing: 16,
              children: [
                Expanded(
                  child: Container(
                    padding: const EdgeInsets.all(16),
                    color: Colors.green.shade100,
                    child: Text('Income\nRs. $income'),
                  ),
                ),
                Expanded(
                  child: Container(
                    padding: const EdgeInsets.all(16),
                    color: Colors.red.shade100,
                    child: Text('Expense\nRs. $expense'),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
An indigo Balance Rs. 25000 card above a green Income box and a red Expense box
Example 5

Expanded works vertically too: the middle part fills the space between a fixed header and footer.

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Example 6')),
      body: Column(
        children: [
          Container(height: 120, color: Colors.purple.shade200),
          Expanded(child: Container(color: Colors.purple.shade50)),
          Container(height: 60, color: Colors.purple.shade300),
        ],
      ),
    );
  }
}
A purple header band, a pale purple middle filling the screen, and a darker footer
Example 6

Common Beginner Mistakes

1. child instead of children

dart
import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(
        body: Column(child: Text('Ali')),
      ),
    ),
  );
}
output
error • The named parameter 'child' isn't defined. Try correcting the name to an existing named parameter's name, or defining a named parameter with the name 'child' • lib/main.dart:7:22 • undefined_named_parameter

Row and Column take children: [ ... ], even for a single child.

2. Forgetting the list brackets

dart
import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(
        body: Column(children: Text('Ali'), Text('Sara')),
      ),
    ),
  );
}
output
error • A value of type 'Text' can't be assigned to a parameter of type 'List<Widget>' in a const constructor. Try using a subtype, or removing the keyword 'const' • lib/main.dart:7:22 • const_constructor_param_type_mismatch
error • The argument type 'Text' can't be assigned to the parameter type 'List<Widget>'.  • lib/main.dart:7:32 • argument_type_not_assignable
error • Too many positional arguments: 0 expected, but 1 found. Try removing the extra positional arguments, or specifying the name for named arguments • lib/main.dart:7:45 • extra_positional_arguments_could_be_named

children needs a list: children: [Text('Ali'), Text('Sara')].

3. A long Text in a Row

The overflow stripes from section 10. Wrap the text in Expanded.

4. Expanded outside a Row or Column

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Oops')),
      body: Center(
        child: Expanded(child: Container(color: Colors.red)),
      ),
    );
  }
}
The body completely red
It even looks right — but the console reports an error
output
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞════════════════════════
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.
The ParentDataWidget Expanded(flex: 1) wants to apply ParentData
of type FlexParentData to a RenderObject, which has been set up
to accept ParentData of incompatible type BoxParentData.
Usually, this means that the Expanded widget has the wrong
ancestor RenderObjectWidget. Typically, Expanded widgets are
placed directly inside Flex widgets.
The offending Expanded is currently placed inside a Center

Expanded, Flexible and Spacer only work as direct children of a Row, Column (or Flex). Here it happens to draw, but Flutter reports the mistake every time the screen is built. Remove the Expanded, or put it inside a Row/Column.


Best Practices

  • Use spacing for even gaps, and a SizedBox only where a gap must be different.
  • Wrap any Text that might be long — names, titles, messages — in Expanded when it sits in a Row.
  • Prefer Expanded and flex over fixed widths, so layouts work on every screen size.
  • When a Row or Column does not stretch the way you expect, color it (a Container with a color) to see how big it really is.
  • Break deep nesting into smaller pieces as soon as it gets hard to read — in Lecture 009 we will turn repeated rows into their own widget classes.

Mini Challenge

Build a weather screen for Lahore:

  • Lahore in 24-pixel text, and below it 30°C in 64-pixel bold text, both centered
  • a 24-pixel gap
  • a row of three equal light-blue boxes (Colors.lightBlue.shade100) with 8-pixel gaps, showing Mon 30°, Tue 32° and Wed 29° on two lines each

Try it yourself before opening the solution.

Show solution
dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.lightBlue),
      home: const WeatherScreen(),
    );
  }
}

class WeatherScreen extends StatelessWidget {
  const WeatherScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Weather')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            const Text('Lahore', style: TextStyle(fontSize: 24)),
            const Text(
              '30°C',
              style: TextStyle(fontSize: 64, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 24),
            Row(
              spacing: 8,
              children: [
                Expanded(
                  child: Container(
                    padding: const EdgeInsets.all(12),
                    color: Colors.lightBlue.shade100,
                    child: const Column(children: [Text('Mon'), Text('30°')]),
                  ),
                ),
                Expanded(
                  child: Container(
                    padding: const EdgeInsets.all(12),
                    color: Colors.lightBlue.shade100,
                    child: const Column(children: [Text('Tue'), Text('32°')]),
                  ),
                ),
                Expanded(
                  child: Container(
                    padding: const EdgeInsets.all(12),
                    color: Colors.lightBlue.shade100,
                    child: const Column(children: [Text('Wed'), Text('29°')]),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
Lahore and a large 30°C above three light-blue day boxes
Mini challenge solution

How it works

  1. The outer Column centers its children horizontally by default.
  2. The Row uses spacing: 8, and each day is Expanded, so the three boxes are equal.
  3. Each box holds a small Column with the day and the temperature.

Practice Questions

Beginner

  1. Show Ali, Sara and Zayan in a Column in the exact center of the screen.
  2. Show red, green and blue 60 × 60 squares in a Row, with the first and last touching the 16-pixel padding.
  3. Show a bold 24-pixel title Flutter Essentials with the line Lecture 004 — Row & Column under it, both left-aligned.

Application

  1. Make an orange box take two thirds of the width and a purple box one third, both 100 tall.
  2. Use Spacer to show Total at the left and Rs. 750 at the right.
  3. In a rounded light-orange card, show Karachi at the left and a bold 34°C at the right, both 20 pixels.
  4. Show Icons.info followed by this text without an overflow: "Zayan, your monthly statement is ready. Open the app to see every deposit and withdrawal."

Challenge

  1. Store Sara's marks (math = 90, science = 85). Show her name in bold 28-pixel text, one full-width row per subject (label left, mark right), and a light-blue total row showing 175 / 200, calculated in the string.

Practice Answers

Question 1 — Solution

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Question 1')),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [Text('Ali'), Text('Sara'), Text('Zayan')],
        ),
      ),
    );
  }
}
Ali, Sara and Zayan in the middle of the screen
Question 1

Question 2 — Solution

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Question 2')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Container(width: 60, height: 60, color: Colors.red),
            Container(width: 60, height: 60, color: Colors.green),
            Container(width: 60, height: 60, color: Colors.blue),
          ],
        ),
      ),
    );
  }
}
Red, green and blue squares spread across the top
Question 2

Question 3 — Solution

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Question 3')),
      body: const Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Flutter Essentials',
              style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
            ),
            Text('Lecture 004 — Row & Column'),
          ],
        ),
      ),
    );
  }
}
A bold title with a subtitle beneath, left-aligned
Question 3

Question 4 — Solution

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Question 4')),
      body: Row(
        children: [
          Expanded(
            flex: 2,
            child: Container(height: 100, color: Colors.orange),
          ),
          Expanded(child: Container(height: 100, color: Colors.purple)),
        ],
      ),
    );
  }
}
An orange box two thirds wide next to a purple box
Question 4

Question 5 — Solution

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Question 5')),
      body: const Padding(
        padding: EdgeInsets.all(16),
        child: Row(children: [Text('Total'), Spacer(), Text('Rs. 750')]),
      ),
    );
  }
}
Total left and Rs. 750 right
Question 5

Question 6 — Solution

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Question 6')),
      body: Container(
        margin: const EdgeInsets.all(16),
        padding: const EdgeInsets.all(16),
        decoration: BoxDecoration(
          color: Colors.orange.shade50,
          borderRadius: BorderRadius.circular(12),
        ),
        child: const Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text('Karachi', style: TextStyle(fontSize: 20)),
            Text(
              '34°C',
              style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
            ),
          ],
        ),
      ),
    );
  }
}
A light-orange card with Karachi left and 34°C right
Question 6

Question 7 — Solution

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Question 7')),
      body: const Padding(
        padding: EdgeInsets.all(16),
        child: Row(
          children: [
            Icon(Icons.info),
            SizedBox(width: 8),
            Expanded(
              child: Text(
                'Zayan, your monthly statement is ready. Open the app to see every deposit and withdrawal.',
              ),
            ),
          ],
        ),
      ),
    );
  }
}
An info icon next to two lines of wrapped text
Question 7

Question 8 — Solution

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.blue),
      home: const ReportScreen(),
    );
  }
}

class ReportScreen extends StatelessWidget {
  const ReportScreen({super.key});

  @override
  Widget build(BuildContext context) {
    String name = 'Sara';
    int math = 90;
    int science = 85;

    return Scaffold(
      appBar: AppBar(title: const Text('Report')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          spacing: 8,
          children: [
            Text(
              name,
              style: const TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [const Text('Math'), Text('$math')],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [const Text('Science'), Text('$science')],
            ),
            Container(
              padding: const EdgeInsets.all(12),
              color: Colors.blue.shade50,
              child: Row(
                children: [
                  const Text('Total'),
                  const Spacer(),
                  Text(
                    '${math + science} / 200',
                    style: const TextStyle(fontWeight: FontWeight.bold),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
Sara, Math 90, Science 85 and a light blue Total 175 / 200 row
Question 8

Quick Revision

  1. What is the main axis of a Column?
  2. Which parameter of a Row puts space between children: mainAxisAlignment or crossAxisAlignment?
  3. What is the difference between spaceAround and spaceEvenly?
  4. What does CrossAxisAlignment.stretch do in a Column?
  5. What does MainAxisSize.min change?
  6. How much space does an Expanded child get?
  7. Two children have flex: 3 and flex: 1. What share does each get?
  8. What causes the yellow and black stripes, and what is the usual fix?

Key Takeaways

  • Column lays children top to bottom; Row left to right. Both take children: [ ... ].
  • The main axis follows the children; the cross axis goes across.
  • mainAxisAlignment spreads children along the main axis; crossAxisAlignment lines them up across it.
  • spacing adds even gaps; MainAxisSize.min shrinks the widget to its children.
  • Expanded fills leftover space, flex shares it, Spacer is empty Expanded space.
  • Overflow stripes mean the children need more room than they have — usually fixed with Expanded.

What's Next?

Lecture 005 — Stack & Positioned. Row and Column place widgets next to each other. Next we place them on top of each other — a badge on a corner, text over a banner, a button floating over a card — with Stack and Positioned.