Open In App

Flutter – Flexible Widget

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Flexible is a built-in widget in flutter which controls how a child of base flex widgets that are Row, Column, and Flex will fill the space available to it. The Expanded widget in flutter is shorthand of Flexible with the default fit of FlexFit.tight. Flexible widget plays a very important part in making a responsive app that looks and feels the same across multiple device sizes. But if one wants just basic filling up of spaces by widgets, then Expanded is also a good candidate for that.

Constructor of Flexible Class:

const Flexible(
{Key key,
int flex: 1,
FlexFit fit: FlexFit.loose,
@required Widget child}
)

Properties of Flexible Widget:

  • debugTypicalAncestorWidgetClass: This property takes Type as a parameter to set the ParentData for error messages.
  • fit: This property takes FlexFit value as a parameter. It decides how a Flexible child widget will fill the space available to it. A child widget can choose to take the maximum area with FlexFit.tight value or it can choose a minimum area with FlexFit.loose value. Or it can be assigned FlexFit.values.
  • flex: This property takes an integer as a parameter. It decides the size of the child widget along the main-axis (for Row it is horizontal and vertical for Column) with respect to other children widgets.

Example 1: Non-Responsive App

Dart




import 'package:flutter/material.dart';
 
void main() {
  runApp(MaterialApp(
    home: Scaffold(
        appBar: AppBar(
            title: Text('GeeksforGeeks'),
            backgroundColor: Colors.greenAccent[400],
            leading: IconButton(
              icon: Icon(Icons.menu),
              onPressed: () {},
              tooltip: 'Menu',
            ) //IconButton
            ), //AppBar
        body: Center(
          child: Container(
              child: Padding(
            padding: const EdgeInsets.all(14.0),
            child: Column(
              children: <Widget>[
                Row(
                  children: <Widget>[
                    Container(
                      width: 175,
                      height: 175,
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(10),
                        color: Colors.red,
                      ), //BoxDecoration
                    ), //Container
                    SizedBox(
                      width: 20,
                    ), //SizedBox
                    Container(
                        width: 175,
                        height: 175,
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
                          color: Colors.red,
                        ) //BoxDecoration
                        ) //Container
                  ], //<Widget>[]
                  mainAxisAlignment: MainAxisAlignment.center,
                ), //Row
                Container(
                  width: 380,
                  height: 200,
                  decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(10),
                      color: Colors.blue), //BoxDecoration
                ), //Container
                Row(
                  children: <Widget>[
                    Container(
                      width: 180,
                      height: 300,
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(10),
                        color: Colors.cyan,
                      ), //BoxDecoration
                    ), //Container
                    SizedBox(
                      width: 20,
                    ), //SizedBox
                    Container(
                        width: 180,
                        height: 300,
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
                          color: Colors.cyan,
                        ) //BoxedDecoration
                        ) //Container
                  ], //<Widget>[]
                  mainAxisAlignment: MainAxisAlignment.center,
                ), //Row
              ], //<widget>[]
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              crossAxisAlignment: CrossAxisAlignment.center,
            ), //Column
          ) //Padding
              ), //Container
        ) //Center
        ), //Scaffold
 
    debugShowCheckedModeBanner: false,
  )); //MaterialApp
}


Output:

Non-Responsive App

Explanation:  Taking a look at the code we can see that at the top of the screen we have a basic app bar build with AppBar widget containing a leading menu IconButton inside. The background color of the app bar is greenAccent[400] and the icon is having a tooltip saying ‘menu’. In the body of the app, the parent widget is Center followed by Container and Padding. After that, we have a Column widget which is taking a list of widgets as children. In that list, the first widget is a Row which is having two Containers and a SizedBox inside it. The Containers are given a height and width of 175 each and with the help of decoration property the color is set to red and the border-radius to 10. Next is a Container outside the Row with a width of 380 and a height of 200. The color is set to blue and the border-radius to 10. This is followed by another Row containing two Containers inside each having cyan color, a height of 300, and a width of 180. In between the containers, there is a SizedBox widget having a width of 20. In both rows, the main axis-alignment is set to center and in the column, the main axis-alignment is set to spaceBetween the cross axis-alignment is set to center.

We can see in this app there are five containers that do not change their size according to the screen size which means the widgets are not responsive. 

Example 2: Horizontally responsive app.

Dart




import 'package:flutter/material.dart';
 
void main() {
  runApp(MaterialApp(
    home: Scaffold(
        appBar: AppBar(
            title: Text('GeeksforGeeks'),
            backgroundColor: Colors.greenAccent[400],
            leading: IconButton(
              icon: Icon(Icons.menu),
              onPressed: () {},
              tooltip: 'Menu',
            ) //IconButton
            ), //AppBar
        body: Center(
          child: Container(
              child: Padding(
            padding: const EdgeInsets.all(14.0),
            child: Column(
              children: <Widget>[
                Row(
                  children: <Widget>[
                    Flexible(
                      flex: 1,
                      fit: FlexFit.tight,
                      child: Container(
                        height: 175,
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
                          color: Colors.red,
                        ), //BoxDecoration
                      ), //Container
                    ), //Flexible
                    SizedBox(
                      width: 20,
                    ), //SizedBox
                    Flexible(
                      flex: 1,
                      fit: FlexFit.loose,
                      child: Container(
                          height: 175,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(10),
                            color: Colors.red,
                          ) //BoxDecoration
                          ), //Container
                    ) //Flexible
                  ], //<Widget>[]
                  mainAxisAlignment: MainAxisAlignment.center,
                ), //Row
                Flexible(
                  flex: 1,
                  fit: FlexFit.loose,
                  child: Container(
                    width: 380,
                    height: 200,
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(10),
                        color: Colors.blue), //BoxDecoration
                  ), //Container
                ), //Flexible
                Row(
                  children: <Widget>[
                    Flexible(
                      flex: 2,
                      fit: FlexFit.tight,
                      child: Container(
                        width: 180,
                        height: 300,
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
                          color: Colors.cyan,
                        ), //BoxDecoration
                      ), //Container
                    ), //Flexible
                    SizedBox(
                      width: 20,
                    ), //SizedBox
                    Flexible(
                        flex: 2,
                        fit: FlexFit.tight,
                        child: Container(
                            width: 180,
                            height: 300,
                            decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(10),
                              color: Colors.cyan,
                            ) //BoxDecoration
                            ) //Container,
                        ) //Flexible
                  ], //<widget>[]
                  mainAxisAlignment: MainAxisAlignment.center,
                ), //Row
              ], //<Widget>[]
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              crossAxisAlignment: CrossAxisAlignment.center,
            ), //Column
          ) //Padding
              ), //Container
        ) //Center
        ), //Scaffold
 
    debugShowCheckedModeBanner: false,
  )); //MaterialApp
}


Output:

Horizontally responsive app.

Explanation: Again by taking a look at the code of the app we can see that this time each Container widget is rapped with the Flexible widget. Inside the Container widgets in the top Row, the flex property is set to 1 for both the Containers which controls how the area will be distributed among these, and the fit property is set to FlexFlit.loose for both which makes sure that both these containers widgets have the option to take minimum area. And again for the blue Container, the flex property is set to 1, and the fit property is set to FlexFlit.loose. In the Container widgets of the bottom Row the flex property is set to 2, they are also going to take equal half-space, we have achieved the same result by making the flex to 1 in the Top Row. And the fit, in this case, is set to FlexFit.tight for both the Containers which will force them to take the maximum space available to them.

One can see that when the screen size is increased in the horizontal direction the width of the containers in the rows changes to adjust according to the screen size, but the blue container does not change its width as it is a direct child of Column and Flexible widget only allows the change of the size of the child along the main axis of the parent widget which is vertical in case of Column. And when the screen size is changed in the vertical direction we can see that the height of the blue Container changes but other containers are not responsive in this direction as they are a child of the Row widget. 

Example 3: Wrapping the top and bottom Row widgets with Flexible widgets

Dart




import 'package:flutter/material.dart';
 
void main() {
  runApp(MaterialApp(
    home: Scaffold(
        appBar: AppBar(
            title: Text('GeeksforGeeks'),
            backgroundColor: Colors.greenAccent[400],
            leading: IconButton(
              icon: Icon(Icons.menu),
              onPressed: () {},
              tooltip: 'Menu',
            ) //IconButton
            ), //AppBar
        body: Center(
          child: Container(
              child: Padding(
            padding: const EdgeInsets.all(14.0),
            child: Column(
              children: <Widget>[
                Flexible(
                  flex: 1,
                  fit: FlexFit.tight,
                  child: Row(
                    children: <Widget>[
                      Flexible(
                        flex: 1,
                        fit: FlexFit.tight,
                        child: Container(
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(10),
                            color: Colors.red,
                          ), //BoxDecoration
                        ), //Container
                      ), //Flexible
                      SizedBox(
                        width: 20,
                      ), //SizedBox
                      Flexible(
                        flex: 1,
                        fit: FlexFit.tight,
                        child: Container(
                            decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
                          color: Colors.red,
                        ) //BoxDecoration
                            ), //Container
                      ) //Flexible
                    ], //<Widget>[]
                    mainAxisAlignment: MainAxisAlignment.center,
                  ), //Row
                ), //Flexible
                SizedBox(
                  height: 20,
                ), //SizedBox
                Flexible(
                  flex: 1,
                  fit: FlexFit.tight,
                  child: Container(
                    width: 380,
                    height: 200,
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(10),
                        color: Colors.blue), //BoxDecoration
                  ), //Container
                ), //Flexible
                SizedBox(
                  height: 20,
                ), //SizedBox
                Flexible(
                  flex: 2,
                  fit: FlexFit.tight,
                  child: Row(
                    children: <Widget>[
                      Flexible(
                        flex: 2,
                        fit: FlexFit.tight,
                        child: Container(
                          width: 180,
                          height: 300,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(10),
                            color: Colors.cyan,
                          ), //BoxDecoration
                        ), //Container
                      ), //Flexible
                      SizedBox(
                        width: 20,
                      ), //SizedBox
                      Flexible(
                        flex: 2,
                        fit: FlexFit.tight,
                        child: Container(
                            width: 180,
                            height: 300,
                            decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(10),
                              color: Colors.cyan,
                            ) //BoxDecoration
                            ), //Container
                      ) //Flexible
                    ], //<Widget>[]
                    mainAxisAlignment: MainAxisAlignment.center,
                  ), //Row
                ), //Flexible
              ], //<Widget>[]
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              crossAxisAlignment: CrossAxisAlignment.center,
            ), //Column
          ) //Padding
              ), //Container
        ) //Container
        ), //Scaffold
 
    debugShowCheckedModeBanner: false,
  )); //MaterialApp
}


Output: 

the top and bottom Row widgets with Flexible widgets

Explanation: Now, in this app, we have wrapped the top and bottom Row widgets with Flexible widgets with each having a flex value of 1. All the fit properties in this app are changes to FlexFit.tight to force child widgets to take all the space available to them. There is also an addition of two SizeBox widgets, one on the top of the blue Container and one below that.

Again taking a look at the app we can see that when screen size changes in the vertical direction the height of all the containers also change according to that, but when screen size changes in the horizontal direction, except the blue container width of all the containers changes also. This is due to the reason the blue Container is just a direct child of the Column widget which allows it to change direction in the only vertical direction. Though we can also make the blue Container responsive by rapping it with a Row widget, which will give it the ability to adjust its size in the horizontal direction as well when wrapped with Flexible,

So, this is how we can make widgets of the whole application responsive in a flutter, by using the Flexible widget.



Last Updated : 21 Feb, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads