The core of Flutter's layout mechanism is widgets.
- Widgets are classes used to build UIs.
- Widgets are used for both layout and UI elements.
- Compose simple widgets to build complex widgets.
Container is a widget class that allows you to customize its child widget. Use a Container when you want to add padding, margins, borders, or background color, to name some of its capabilities.
Text widget:
Text('Hello World'),
Image widget:
Image.asset(
'images/lake.jpg',
fit: BoxFit.cover,
),
Icon widget:
Icon(
Icons.star,
color: Colors.red[500],
),
All layout widgets have either of the following:
- A
child
property if they take a single child—for example,Center
orContainer
- A
children
property if they take a list of widgets—for example,Row
,Column
,ListView
, orStack
.
A Flutter app is itself a widget
, and most widgets have a build()
method.
For a Material
app, you can use a Scaffold widget. It provides:
- a default banner
- background color
- has API for adding:
- drawers
- snack bars
- bottom sheets
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter layout demo',
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter layout demo'),
),
body: const Center(
child: Text('Hello World'),
),
),
);
}
}
When designing your UI, you can exclusively use widgets from the standard widgets library, or you can use widgets from the Material library.
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(color: Colors.white),
child: const Center(
child: Text(
'Hello World',
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 32,
color: Colors.black87,
),
),
),
);
}
}
Non-Material app doesn't include an AppBar
, title, or background color. If you want these features in a non-Material app, you have to build them yourself.
Row
andColumn
are two of the most commonly used layout patterns.Row
andColumn
each take a list of child widgets.- A child widget can itself be a
Row
,Column
, or other complex widget. - You can specify how a
Row
orColumn
aligns its children, both vertically and horizontally. - You can stretch or constrain specific child widgets.
- You can specify how child widgets use the
Row
's orColumn
's available space.
Flutter also offers specialized, higher level widgets that might be sufficient for your needs like:
- Instead of
Row
, ListTile is an widget with properties for leading and trailing icons, and up to 3 lines of text. - Instead of Column, ListView, is a column-like layout that automatically scrolls if its content is too long to fit the available space.
For more information, see Common layout widgets.
Control how a row
or column
aligns its children using the mainAxisAlignment
and crossAxisAlignment
properties.
The MainAxisAlignment and CrossAxisAlignment enums offer a variety of constants for controlling alignment.
spaceEvenly
divides the free space evenly between, before, and after each widget.
Widgets can be sized to fit within a row or column by using the Expanded widget.
Use the Expanded
widget flex
property, an integer that determines the flex factor (default to 1) for a widget, to allow a widget to occupy the space as n
times as its siblings. For example we want to occupy twice as much, set flex
to 2:
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Image.asset('images/pic1.jpg'),
),
Expanded(
flex: 2,
child: Image.asset('images/pic2.jpg'),
),
Expanded(
child: Image.asset('images/pic3.jpg'),
),
],
);
By default, a row or column occupies as much space along its main axis as possible.
To pack the children closely together, set its mainAxisSize
to MainAxisSize.min
.
To minimize the visual confusion that can result from heavily nested layout code, implement pieces of the UI in variables and functions.
- When add images, update the
pubspec.yaml
file to access them → see this example's pubspec.yaml file or Adding assets and images. - When referencing online images using
Image.network
, don't need to do anything.
The Pavlova image runs best horizontally on a wide device, such as a tablet. App source: pavlova
- Container: Adds padding, margins, borders, background color, or other decorations to a widget. → Demo
- Contains a single child widget, but that child can be a Row, Column, or even the root of a widget tree.
- GridView: Lays widgets out as a scrollable grid. → Demo
- Detects when the column content exceeds the render box and automatically provides scrolling.
- Build your own custom grid, or use one of the provided grids:
GridView.count
allows you to specify the number of columns.GridView.extent
allows you to specify the maximum pixel width of a tile.
- ListView: Lays widgets out as a scrollable list → Demo
- A specialized
Column
for organizing a list of boxes. - Can be laid out horizontally or vertically.
- Detects when its content won't fit and provides scrolling.
- Less configurable than
Column
, but easier to use and supports scrolling.
- A specialized
- Stack: Overlaps a widget on top of another → Demo
- The first widget in the list of children is the base widget; subsequent children are overlaid on top of that base widget
- A
Stack
's content can't scroll. - can clip children that exceed the render box.
- Card: Organizes related info into a box with rounded corners and a drop shadow → Demo
- Used for presenting related nuggets of information.
- Accepts a single child, but that child can be a Row, Column, or other widget that holds a list of children.
- Displayed with rounded corners and a drop shadow.
- A Card's content can't scroll.
- ListTile: Organizes up to 3 lines of text, and optional leading and trailing icons, into a row → Demo
- A specialized row that contains up to 3 lines of text and optional icons.
- Less configurable than Row, but easier to use.