Flutter Layout Basics
Before starts to develop a flutter application everyone should understand that the Flutter layout is very different from the HTML layout. So, First of all, I’ll discuss why the flutter layout is different from the HTML layout.
According to the flutter documentation,
Constraints go down. Sizes go up. Parent sets position.
Constraints of a widget cannot be decided by itself because constraints are given to a widget by its parent widget. So, widgets can have sizes only within those constraints.
The position of a widget is also can`t be decided by the widget itself. The positions of their children widgets should be decided by the parent widget.
Let’s create a few sample widgets to understand about flutter layout.
In our Scaffold body of the project let’s place a column that has the full-screen size for width and height.
Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: ConstrainedBox(
constraints: BoxConstraints.tightFor(
width: double.infinity, height: double.infinity
),
child: ExampleWidget()
),
),
],
),
)
In the ExampleWidget,
You can see that although we have set both the height and width of the container to 100 the container fills the entire screen. what happens here is the parent widget of the container forces the child to be the same size as the screen. So, we can see that widgets can’t have their desired sizes.
Container(
height: 100,width: 100,
color: Colors.blue
)
If we use a Center widget to wrap the above container, the Center widget will be forced to have the exactly same size as the screen.
But here the Center widget has allowed its child widgets to have any desired size within the screen size.
So, the child container will have a size of 100 x 100.
Center(
child: Container(
height: 100,
width: 100,
color: Colors.blue
)
)
The Align Widget is also working as same as the Center widget.
But, using the Align widget we can provide a desired position to the child widget on the screen.
Align(
alignment: Alignment.topCenter,
child:Container(
height:100,
width:100,
color: Colors.blue
)
)
Let`s create a sample widget from the above concepts…
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(5),
height: 100,
width: 300,
color: Colors.blue,
child: Row(
children: <Widget>[
Expanded(
child: Container(
width: 70,
color:Colors.red
),
),
],
),
)
Although we have defined the width as 70 for the red container, the Expanded widget has forced it to have the expanded width. So, the defined width will be ignored.
Since we haven`t defined a value for the height of the red container and also it doesn’t have a child widget, here it is having the maximum possible height.
When there`s a child widget for the red container …
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(5),
height: 100,
width: 300,
color: Colors.blue,
child: Row(
children: <Widget>[
Expanded(
child: Container(
color:Colors.red,
child: Text(
'Child Widget of the Red Container',
style: TextStyle(fontSize: 20),
),
),
),
],
),
)
But if there`s a child widget for the red container, then it will take the same height as its child widget as above.
Let`s see what happens when there are multiple children.
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(5),
height: 100,
width: 300,
color: Colors.blue,
child: Row(
children: <Widget>[
SizedBox(
width: 80,
child: Container(
color:Colors.purple
),
),
Expanded(
child: Container(
color: Colors.red,
),
),
],
),
)
In the above widget, there are two children in a row and one is an Expanded widget. In this situation, the Expanded widget(red) takes the whole width after giving the width for the other child widget(purple) in the row.
Think of a situation where all the row children are wrapped using Expanded widgets.
In that situation, each expanded widget takes the width according to the flex parameter of the Expanded widget.
In this example, we are trying to place a long text inside the red container. Then the text will get the maximum width which is possible and break into several lines if needed.
Also here there is a child widget for the red container. As we discussed before, since the height of the container is not defined, the container will decide to take the size of its child widget.
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(5),
height: 100,
width: 300,
color: Colors.blue,
child: Row(
children: <Widget>[
SizedBox(
width: 80,
child: Container(
color: Colors.purple,
),
),
Expanded(
child: Container(
width: 70,
color: Colors.red,
child: Text('This is some long text for example card
description', style: TextStyle(fontSize: 15)),
),
),
],
),
)
If we wrap the text widget using a FittedBox, it will automatically scale the text until it fills the available width instead of breaking text into several lines.
Here also the red container will take the size of the FittedBox as the height of the container is not defined.
Let`s see the below code to get clear about this concept.
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(5),
height: 100,
width: 300,
color: Colors.blue,
child: Row(
children: <Widget>[
SizedBox(
width: 80,
child: Container(
color: Colors.purple,
),
),
Expanded(
child: Container(
width: 70,
color: Colors.red,
child: FittedBox(
child: Text(
'This is some long text for example card description',
style: TextStyle(fontSize: 15),
),
),
),
),
],
),
)
A child widget with an infinity height.
We can set the height of the container(red) as infinity. Then the container is trying to take infinity height. In this situation, the parent widget is allowing the child widget to take any size it wants but not bigger than the height of the row. That`s why the red container is getting the maximum possible height which is the height of the row.
Here I have explained only a few basic concepts used in making flutter layouts, which I thought will be useful for a beginner in Flutter.
For better understanding, you can refer to the full code of this project using the following git repository.