How to think about flutter layouts

Let's be real specific here. Note the following specific question and the specific answer.

Question: What determines the size of a widget in flutter?
Answer: The widget can size itself however it wants but it is limited by the constraints imposed by its immediate parent widget. Widgets might also change their behavior entirely when it receives no constraints/is unconstrained. For instance, when a Column receives fixed constraints, like 0.0 <= h <= 100.3 and 0.0 <= w <= 958, it will try to assume the maximum height it can: 100.3. It chooses only enough width to fit its widest child, within the constraints ofcourse. But when the Column widget receives unbounded constraints, it no longer sets its height to the maximum it can, which is rational since the maximum would be infinity under unbounded constraints.

In a typical layout we create which starts with a Column (or Row), it receives fixed constraints and chooses to be biggest it can along its main axis. So a Column fills out the whole screen. This is what I mean by a typical layout:

import 'package:flutter/material.dart';

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

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: Scaffold(
        appBar: AppBar(title: Text('Layout study')),
        body: const MyHomePage(),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Hello There'),
      ],
    );
  }
}

Our layout process for the app stars from the Column. Look at devtools to see what the layout looks like, pay attention to the constraints Column receives and what it decides its size is gonna be.

1732826833.png

You can see it choose the maximum of height from the the constraint and just enough width to fit the child Text widget.

Also note here that the child of this Column receives unconstrained height. We can exploit this fact by having one of the child widget take infinite height. As I mentioned earlier, when a Column receives unbounded height, it tries to do the rational next best thing, to be tall enough to fit its children. What happens if one those children say it wants to be too taller beyond the height of screen:

Column(
  children: [
    Container(
      width: 100,
      height: 5000,
      color: Colors.blue,
    ),
  ],
)
Now we get the classic overflow error. This is what we see in devtools:

1732829021.png

And this on the display:

1732829047.png

Look at the layout as shown in flutter inspector again and note that Column passes definite constraints width-wise to the child. So it has no problem rendering this despite the widget trying to set its width to something larger than the screen.

Column(
  children: [
    Container(
      width: 5000,
      height: 100,
      color: Colors.blue,
    ),
  ],
)

Comments