What you’ll learn

This is a guide to building layouts in Flutter.
You’ll build the layout for the following app:

The finished app

This guide then takes a step back to explain Flutter’s approach to layout,
and shows how to place a single widget on the screen.
After a discussion of how to lay widgets out horizontally and vertically,
some of the most common layout widgets are covered.

First, identify the larger elements. In this example, four elements are
arranged into a column: an image, two rows, and a block of text.

Column elements (circled in red)

Next, diagram each row. The first row, called the Title
section, has 3 children: a column of text, a star icon,
and a number. Its first child, the column, contains 2 lines of text.
That first column takes a lot of space, so it must be wrapped in an
Expanded widget.

The second row, called the Button section, also has
3 children: each child is a column that contains an icon and text.

Once the layout has been diagrammed, it’s easiest to take a bottom-up
approach to implementing it. To minimize the visual
confusion of deeply nested layout code, place some of the implementation
in variables and functions.

Step 2: Implement the title row

First, you’ll build the left column in the title section. Add the following code
at the top of the build() method of the MyApp class:

Putting a Column inside an Expanded widget stretches the column to use all
remaining free space in the row. Setting the crossAxisAlignment property to
CrossAxisAlignment.start positions the column at the start of the row.

Putting the first row of text inside a Container enables you to add padding.
The second child in the Column, also text, displays as grey.

The last two items in the title row are a star icon, painted red,
and the text “41”. The entire row is in a Container and padded
along each edge by 32 pixels.

Step 3: Implement the button row

The button section contains 3 columns that use the same layout—an
icon over a row of text. The columns in this row are evenly spaced,
and the text and icons are painted with the primary color.

Since the code for building each column is almost identical, create a private
helper method named buildButtonColumn(), which takes a color, an Icon and
Text, and returns a column with its widgets painted in the given color.

The function adds the icon directly to the column. The text is inside a
Container with a top-only margin, separating the text from the icon.

Build the row containing these columns by calling the function and passing the
color, Icon, and text specific to that column. Align the columns along the main axis
using MainAxisAlignment.spaceEvenly to arrange the free space evenly before,
between, and after each column. Add the following code just below the
titleSection declaration inside the build() method:

Step 4: Implement the text section

Define the text section as a variable. Put the text in a Container and add
padding along each edge. Add the following code just below the buttonSection
declaration:

lib/main.dart (textSection)

Widget textSection = Container(
padding: const EdgeInsets.all(32),
child: Text(
'Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese '
'Alps. Situated 1,578 meters above sea level, it is one of the '
'larger Alpine Lakes. A gondola ride from Kandersteg, followed by a '
'half-hour walk through pastures and pine forest, leads you to the '
'lake, which warms to 20 degrees Celsius in the summer. Activities '
'enjoyed here include rowing, and riding the summer toboggan run.',
softWrap: true,
),
);

By setting softwrap to true, text lines will fill the column width before
wrapping at a word boundary.

Add the text section to the body:

{step3 → step4}/lib/main.dart

@@ -59,3 +72,3 @@

59

72

return MaterialApp(

60

73

title: 'Flutter layout demo',

61

74

home: Scaffold(

@@ -66,6 +79,7 @@

66

79

children: [

67

80

titleSection,

68

81

buttonSection,

82

+ textSection,

69

83

],

70

84

),

71

85

),

Step 5: Implement the image section

Three of the four column elements are now complete, leaving only the image.
Add the image file to the example: