Skip to main content

Build a Flutter layout

Learn how to build a layout in Flutter.

This tutorial explains how to design and build layouts in Flutter.

If you use the example code provided, you can build the following app.

The finished app.

The finished app.

Photo by Dino Reichmuth on Unsplash. Text by Switzerland Tourism.

To get a better overview of the layout mechanism, start with Flutter's approach to layout.

Diagram the layout

#

In this section, consider what type of user experience you want for your app users.

Consider how to position the components of your user interface. A layout consists of the total end result of these positionings. Consider planning your layout to speed up your coding. Using visual cues to know where something goes on screen can be a great help.

Use whichever method you prefer, like an interface design tool or a pencil and a sheet of paper. Figure out where you want to place elements on your screen before writing code. It's the programming version of the adage: "Measure twice, cut once."

  1. Ask these questions to break the layout down to its basic elements.

    • Can you identify the rows and columns?
    • Does the layout include a grid?
    • Are there overlapping elements?
    • Does the UI need tabs?
    • What do you need to align, pad, or border?
  2. Identify the larger elements. In this example, you arrange the image, title, buttons, and description into a column.

    Major elements in the layout: image, row, row, and text block

    Major elements in the layout: image, row, row, and text block

  3. Diagram each row.

    1. Row 1, the Title section, has three children: a column of text, a star icon, and a number. Its first child, the column, contains two lines of text. That first column might need more space.

      Title section with text blocks and an icon

      Title section with text blocks and an icon

    2. Row 2, the Button section, has three children: each child contains a column which then contains an icon and text.

      The Button section with three labeled buttons

      The Button section with three labeled buttons

After diagramming the layout, consider how you would code it.

Would you write all the code in one class? Or, would you create one class for each part of the layout?

To follow Flutter best practices, create one class, or Widget, to contain each part of your layout. When Flutter needs to re-render part of a UI, it updates the smallest part that changes. This is why Flutter makes "everything a widget". If only the text changes in a Text widget, Flutter redraws only that text. Flutter changes the least amount of the UI possible in response to user input.

For this tutorial, write each element you have identified as its own widget.

Create the app base code

#

In this section, shell out the basic Flutter app code to start your app.

  1. Set up your Flutter environment.

  2. Create a new Flutter app.

  3. Replace the contents of lib/main.dart with the following code. This app uses a parameter for the app title and the title shown on the app's appBar. This decision simplifies the code.

    dart
    import 'package:flutter/material.dart';
    
    void main() => runApp(const MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        const String appTitle = 'Flutter layout demo';
        return MaterialApp(
          title: appTitle,
          home: Scaffold(
            appBar: AppBar(title: const Text(appTitle)),
            body: const Center(
              child: Text('Hello World'),
            ),
          ),
        );
      }
    }
    

Add the Title section

#

In this section, create a TitleSection widget that resembles the following layout.

The Title section as sketch and prototype UI

The Title section as sketch and prototype UI

Add the TitleSection Widget

#

Add the following code after the MyApp class.

dart
class TitleSection extends StatelessWidget {
  const TitleSection({super.key, required this.name, required this.location});

  final String name;
  final String location;

  @override
  Widget build(BuildContext context) {
    return Padding(