Creating Responsive Layouts Part III: Understanding Flexible and Expanded
Understanding Flex Family in flutter for creating Responsive Layouts
Note: This blog assumes that you are using vscode, Android Studio or IntelliJ as IDE.
This is the third part in the Creating Responsive Layouts series and focuses on Flexible and Expanded widgets. The previous article can be found here.
In this blog we will look how Flexible and Expanded widgets work and learn how to use them for creating a Responsive Layouts in Flutter.
- A bit about the Flex family
- Introduction Flexible and Expanded widgets
- Understanding the flex factor
- Conclusion
So, without a further ado lets jump right in.
A bit about the Flex family
To kick things of let’s first discuss about the flex family of widgets.
Well, Flex is acthually a class, but we will be refering the widget’s that use Flex as its parent(super class) being part of the flex family.
Basically, the sub classes that extend the Flex and related classes are part of the “flex family” of widgets.
For some beginners, Flex might be a new word and might confuse them. But, we have all used Flex widget in the form of Row and Column. If we look at the code of Row and Column they both extend the Flex class. The only difference being the Axis direction. Row by default has direction of Axis.horizontal and Column by default has direction of Axis.vertical.
So we can say that,
Row is a Flex widget which lay’s out its childrens “horzontally” and Column is a Flex widget which lay’s out its childrens “vertically”.
Alos, We can put Flexible and Expanded widgets in the same family because of the close relation that these widgets have with the other Flex family widgets.
Now, since we have discussed about the Flex widgets its time to move to the next section.
Introduction Flexible and Expanded widgets
Let’s say we have a Row with some fixed size widgets in it. As we keep on adding more widgets we will arrive at the point were the widgets might not fit themselves in this Row and flutter will throw the RenderFlex overflowed error that we all hate.
The reason we had this error in the first place was because of the use of fixed size widgets. The first lesson to keep in mind while creating responsive layouts is
“Do Not Use Fixed Values for Determining Widget Size”
If using fixed values for sizing widgets we might end up getting the RenderFlex Overflowed error in one device or the other. So what’s the solution?
Well, the solution is eazy peasy. We can use relative sizes with help from either MediaQuery or LayoutBuilder widgets. Problem Solved….
Well, technically, the problem is solved and we won’t get any errors, but, here are some thing we need to consider before using MediaQuery or LayoutBuilder.
- Both MediaQuery and LayoutBuilder require a little boilerplate code before they can be of any use.
- As discussed in previous articles of the series, using MediaQuery excessively can lead to performance issues. Same can be said about LayoutBuilder, any changes in constraints will result in rebuilding of the entire widget tree returned by builder function.
- Even if we can deal with the above two reasons, we will need to make calculations, which can get ugly if you are bad at math as I am, ahh… just kidding. The calculations in such cases are usually simple but it’s better to avoid them whenever possible.
Due to the above reasons it is best to avoid using MediaQuery or LayoutBuilder, inside the flex widgets.
So, what can we do? Are there any options? Maybe some prebuilt widget……
This is were Flexible and Expanded come into play. The good thing about these widgets is that they are a part of the flex family and were made for use inside flex widgets for relative sizing of the childern widgets.
The biggest adavntage of Flexible and Expanded widget is that, it does not require any boilerplate code and it extremely easy to use.
Get Bhavesh Mankar’s stories in your inbox
Join Medium for free to get updates from this writer.
First, let’s have a look on how to use the Flexible widget,
import 'package:flutter/material.dart';
class FlexibleExample extends StatelessWidget {
const FlexibleExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: [
Flexible(
flex: 1,
child: Container(
color: Colors.red,
height: 100,
child: const Center(child: Text('Flex 1')),
),
),
Flexible(
flex: 2,
child: Container(
color: Colors.green,
height: 100,
child: const Center(child: Text('Flex 2')),
),
),
Flexible(
flex: 1,
child: Container(
color: Colors.blue,
height: 100,
child: const Center(child: Text('Flex 1')),
),
),
],
),
);
}
}The above code uses Flexible widget for determing the width of the child Containers. We have specified the flex value which tells Flexible the amount of space that should be accquired by the child widget. The first(red) and last(blue) Container have the same flex value of 1 and will accquire less space in comparison to the second(green) Container which has a flex value of 2 accquiring more space, twice as much as first and second containers in our case. We can say that,
“Higher” the flex value = “Larger” the space accquired
Now, coming towards the Expanded widget, if we look at the code for Expanded it is just a Flexible widget with its FlexFit fit defaulting to FlexFit.tight. Specifiing the FlexFit as tight makes a Flexible fill all the remaining space and for the ease of use and understanding, this Flexible is “termed” as Expanded.
Let’s take a look at another code:
import 'package:flutter/material.dart';
class ExpandedExample extends StatelessWidget {
const ExpandedExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: [
Flexible(
flex: 10,
child: Container(
color: Colors.red,
height: 100,
child: const Center(child: Text('Flex 1')),
),
),
Container(
color: Colors.green,
height: 100,
width: 200,
child: const Center(child: Text('Fixed Width Container')),
),
Expanded(
child: Container(
color: Colors.teal,
height: 100,
child: const Center(child: Text('Expanded')),
),
),
],
),
);
}
}In the code for ExpandedExample we have a Flexible widget, a fixed width Container and an Expanded widget inside a Row. The Flexible widget accquires the most space with a flex of 10, fixed width container accquires a width of 200 and the Expanded widget fills the remaining space.
If we were to run the same code across devices of different screen dimensions we would get the same output. Aint’t that great.
OK. All of that is good, but what’s the thing with the flex value. Higher the flex value means larger the space accquired is understandable, but
How does flutter calculates the size of widgets based on flex value?
Well, that brings us to the next section of the article.
Understanding the flex factor
In order to fully understand how Flexible and Expanded work it is essential to understand the flex value or we can also say the “flex factor”.
The flex factor informs flutter about the amount of space the Flexible should accquire across the main axis. We can say that,
Flex Factor determines the amount of space a Flexible should accquire relative to other widgets.
This could be understood by a taking simple example,
The Pizzamigos
Let’s say there were three friends who have ordered a large pizza and they decide to distribute the pizza based on how hungry they are. The first friend is not that hungry so get’s a single pizza slice. The second friend is starving and gets 5 pizza slices. The third firend is hungry as well gets 4 slices.
Now, going by that analogy,
The pizza is the “available space”,
friends are the “widgets” and
slices are the “flex factor”.
Suppose that we have available width of 400px and we use a Row with three Containers. Since we want a responsive layout we use Flexible to hold containers and specify the flex factor as 1, 5 and 4 respectively.
Now, during layout process after determining the available space, flutter
- First adds the flex values 1 + 5 + 4 = 10 and calculates the size of individual part 1 part = 400px/10 = 40px
- Then it, sub divides the available width into 10 parts.
- Next flutter calculates space requested by each Flexible via flex factor
- The first container with a flex factor of 1 gets 1 part from the available space (1 * 40 pixels = 40 pixels).
- The second container with a flex factor of 5 gets 5 parts from the available space (5 * 40 pixels = 200 pixels).
- The third container with a flex factor of 4 gets 4 parts from the available space (4 * 40 pixels = 160 pixels).
Just like the pizza slices are divided among the friends based on how hungry they are, the available space in a Row or Column or Flex is divided among the widgets based on their respective flex factors. This ensures that space distribution relative and helps in Creating Responsoive Layouts.
Conclusion
In this article, we had an overview of Flex family in Flutter and origins of Row and Column widgets. Then we learned about Flexible and Expanded widgets, which help in creating responsive layouts by relatively sizing widgets based the flex factor. We also had a look at how the flex factor determines the size of widgets. Understanding these concepts is essential for designing flexible and well-balanced layouts in Flutter.
For reading the entire blog,







