Flutter flexible widgets: Row
Flutter provides several layout widgets that help build UI easily. Let's explore how the Row widget can be used and configured to build our apps.

When building mobile applications you often have to work on the appearance and layout of your UI elements. Flutter provides a rich collection of layout Widgets that help make this process much simpler.
In this article, we will go through the essentials of the Row widget in Flutter and experiment with some of the common properties that can be used to configure this widget.
How does the Row widget work?
Row is one of Flutter’s fundamental layout widgets, almost every app will use this widget. The Row widget arranges any children provided to it in a horizontal line.
By default, this widget always takes all available space in the horizontal direction. Without any fixed dimensions, Row will also resize itself based on the size of the screen, allowing you to build responsive layouts.
How to use the Row widget?
Let's look at a very basic usage of Row:
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
children: [
SizedBox(
width: 100,
height: 100,
child: Container(
color: Colors.red,
),
),
SizedBox(
width: 100,
height: 100,
child: Container(
color: Colors.blue,
),
),
SizedBox(
width: 100,
height: 100,
child: Container(
color: Colors.green,
),
),
SizedBox(
width: 100,
height: 100,
child: Container(
color: Colors.purple,
),
),
],
),
),
),
);
}
In the code snippet above we have a very simple screen that renders 4 boxes horizontally, the output looks similar to this:

A simple row of boxes
In the example above we use Center and Padding for layout but by default, children are always laid out from the left, however Row can be configured to change this.
Modifying horizontal alignment of the Row
First, let’s look at what the default Row renders without the Padding, we do not need to remove the Center widget for this because it does not affect the horizontal layout of Row.

The Row without the padding
The Row widget accepts a property called mainAxisAlignment which instructs the widget on how to align its children along the main axis. The main axis is the direction along which the widget renders its children, in the case of the Row widget the main axis is horizontal.
You can use the following options for mainAxisAlignment :
start
end
center
spaceAround
spaceBetween
spaceEvenly
start, end and center simply align the children along the axis, start being the left edge by default and end being the right edge.
spaceAround, spaceBetween and spaceEvenly align the children by applying spacing constraints to them.
Using MainAxisAlignment.start
This is the default alignment that Row uses:
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
...,
],
),
),
);
}

The Row using MainAxisAlignment.start for layout
Using MainAxisAlignment.center
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...,
],
),
),
);
}

The Row using MainAxisAlignment.center for layout
Using MainAxisAlignment.end
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...,
],
),
),
);
}

The Row using MainAxisAlignment.end for layout
Using MainAxisAlignment.spaceAround
spaceAround applies equal spacing to all children such that all children have equal spacing between them. The remaining space in the Row is then divided equally at the start and end of the Row.
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
...,
],
),
),
);
}

The Row using MainAxisAlignment.spaceAround for layout
Using MainAxisAlignment.spaceBetween
spaceAround applies equal spacing to all children such that all children have equal spacing between them, but there is no spacing applied to the edges of the Row.
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
...,
],
),
),
);
}

The Row using MainAxisAlignment.spaceBetween for layout
Using MainAxisAlignment.spaceEvenly
spaceAround applies equal spacing to all children such that all children have equal spacing between them and the same amount of spacing is applied to both start and end of the Row itself.
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
...,
],
),
),
);
}

The Row using MainAxisAlignment.spaceEvenly for layout
Modifying vertical alignment of the Row
Along with mainAxisAlignment the widget also accepts a crossAxisAlignment property. The cross axis is the secondary direction along which the widget renders its children, in the case of the Row widget the cross axis is vertical.
You can use the following options for crossAxisAlignment :
start
end
center
baseline
stretch
baseline is a little more nuanced and will be skipped in this article.
Using CrossAxisAlignment.start
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
...,
],
),
),
);
}

The Row using CrossAxisAlignment.start for layout
Using CrossAxisAlignment.center
This is the default alignment that Row uses:
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
...,
],
),
),
);
}

The Row using CrossAxisAlignment.center for layout
Using CrossAxisAlignment.end
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
...,
],
),
),
);
}

The Row using CrossAxisAlignment.end for layout
Using CrossAxisAlignment.stretch
stretch forces all children of the Row to take the same height as the Row itself.
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
height: 300,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
...
],
),
),
),
);
}

The Row using CrossAxisAlignment.stretch for layout
stretch also demonstrates the responsiveness properties of Row . Because of its “flexible” nature, when there are no size constraints provided to Row it takes all available space if its children also request unbounded sizes. When you use stretch it tells its children to take up all available space, and without the Container would result in all children taking the screen height because both the Row and its children would request to take all available space.
Modifying how much space Row takes
Now that we know that Row tries to make as much space as possible by default, we have identified one issue with building our layouts. In our example even though we use Center the items in the Row are still laid out using the left edge of the screen.

The children are always laid out at the start of the Row
This is because the Row has an unbounded width constraint so it uses screen width and by default the alignment along the main axis is the start of the Row.
Row accepts a property called mainAxisSize which controls how much space it takes along the Main Axis (i.e horizontal). You can use the following values for mainAxisSize :
min
max
Using MainAxisSize.min
min instructs the widget to constrain its size along the main axis to be equal to the width constraint of its children (including any padding or spacing the children may have)
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
...
],
),
),
);
}

The Row is now rendered in the center of the screen
Because min makes the Row size according to its children, the layout constraints imposed by Center start to work as expected.
Using MainAxisSize.max
This is the default size that Row uses.
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
...
],
),
),
);
}

Row takes full-screen width
The Row widget is extremely useful when it comes to building mobile applications and with some basic configuration, you can use it to create great-looking UI really easily!




