Building a responsive screen layout means writing a piece of code that responds to various changes in the device layout, so the application displays its UI based on the device’s screen size and shape.

In this article, we will explore the expansion and flexibility of Flutter for screen response.

Because of Flutter’s cross-platform, single code base capabilities, it is crucial to understand screen management to prevent problems like flexible overflow errors or poor user interface design.

We will also design a demo of extended and flexible widgets and describe their properties and how to use them in the Flutter application.

The premise condition

To understand and follow this tutorial, you should have the following conditions.

  • Install Flutter on your local machine
  • Working knowledge of Flutter and Dart

The problem with using containers

In a Flutter, a container is a parent widget that contains multiple child widgets. It manages them by width, height, background color and padding, and other descriptors. Basically, a container is a box that we can pass content into.

There are two reasons why using containers to create a responsive screen layout in Flutter is not advisable.

The first is RenderFlex overflow **. ** This is one of the most frequently encountered Flutter framing errors; When it happens, you’ll see yellow and black stripes indicating overflow areas in the application UI, along with error messages from the debug console.

“Insufficient content size for large screens” is just a UI error, due to the flexibility of Flutters, content is too small or too large for a particular screen.

Both of these issues can be addressed using “flexible” or “extended” widgets to provide a better UI and development experience.

Introduction of expanded panels

An extension widget is a monad widget, meaning that only one subitem can be assigned to it. For better optimization, it is used in rows or columns.

Attributes for extended widgets include Child widgets and Flex widgets.

The Child widget is placed inside an extended widget, which can receive progress and columns. Flex is used to unevenly distribute the contents of the Child widget.

In the code below, we use the enlarged widget, set Flex to 1, and use a plain container to display the effects of the enlarged widget and its properties.

Expanded(
 flex: 1,
 child: Container(
 color: Colors.red,
 ),
),

Copy the code

Introduction of flexible components

Flexible widgets are quite similar to “extended” widgets, but the significant difference lies in their attributes. Flexible widgets are used to adjust the placement of the child’s content on the screen.

Flexible part properties include FIT and Flex.

Fit controls how this property fills the available space. It has two options: flexfit.tight, which is set to fill the available space, and flexfit.loose, which fills the remaining free space of the subwidget.

Just as in the “extend” widget, Flex is used to unevenly distribute the content of the subwidget.

The following code uses a Flexible Widget whose Flex is set to 1, suitable for flexfit.loose, and a child container with regular functionality.

Flexible(
   flex: 1,
   fit: FlexFit.loose,
   child: Container(
   height: 100,
    decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(15),
      color: Colors.deepOrange[400],
      ),
    child:Icon(Icons.backpack),
 ),
),

Copy the code

Set up a sample application

In this demo, we will create a Flutter sample application with a layout that displays content in rows and columns.

Here’s a GIF showing the demo application we’ll build in this article.

Let’s create a Flutter project directory first; Enter the following command in your terminal.

mkdir FlutterApps
Copy the code

Next, create a Flutter project.

flutter create sample_app
Copy the code

Now open the Flutter project in any code editor you choose.

Code execution

Paste the following code into the main.dart file. We’ll start by creating a stateful widget called homepage.

In homepage, we’ll create two buttons that lead us to two different screens to see the difference between using extensions and flexible widgets in the screen layout.

Scaffold(
  body: Center(
    child:
      Column(mainAxisAlignment: MainAxisAlignment.center, children: [
 GestureDetector(
  onTap: () {
   Navigator.push(
    context,
    MaterialPageRoute(
     builder: (context) => ExpandedWidget(),
    ),
   );
  },
  child: Container(
    height: 50,
    width: 150,
    decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(10), color: Colors.red),
    child: Center(child: Text("Expanded Widget"))),
 ),
 SizedBox(height: 100),
 GestureDetector(
  onTap: () {
   Navigator.push(
    context,
    MaterialPageRoute(
     builder: (context) => FlexibleWidget(),
    ),
   );
  },
  child: Container(
    height: 50,
    width: 150,
    decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(10),
      color: Colors.teal[700]),
    child: Center(child: Text("Flexible Widget"))),
 )
])));

Copy the code

The buttons created are simple containers with decorations, colors, and text widgets wrapped in a gesture detector that allows us to use the onTap property to navigate to ExpandedWidget() and FlexibleWidget() screens.

Extended widget examples

First, create a file called expanded. Dart.

touch expanded.dart

Copy the code

Next, paste the following code into the file. In the code, we created a stateless widget to write our example using flex properties.

class ExpandedWidget extends StatelessWidget { const ExpandedWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: GestureDetector( onTap: () { Navigator.pop(context); }, child: Icon(Icons.arrow_back_ios_new)), ), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 15), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Column( children: [ Text("With Flex"), Container( height: 100, child: Row( children: [ Expanded( flex: 1, child: Container( color: Colors.red, ), ), Expanded( flex: 2, child: Container( color: Colors.deepOrange[400], ), ), Expanded( flex: 3, child: Container( color: Colors.purpleAccent, ), ) ], ), ), ], ), Column( children: [ Text("Without Flex"), Container( height: 100, child: Row( children: [ Expanded( child: Container( color: Colors.red, ), ), Expanded( child: Container( color: Colors.deepOrange[400], ), ), Expanded( child: Container( color: Colors.purpleAccent, ), ) ], ), ), ], ), ], ), )); }}Copy the code

First, we return a scaffold so that we can use the AppBar and body properties. Next, in appBar, we create a back button so that we can return to the previous screen.

Next to the body, we use two columns, one at the top and one at the buttons to separate them; In each column, we have a paragraph describing whether it has or does not have Flex. Below it, we created a row using three extensions with or without Flex and a container that assigned different colors.

The following image shows the layout with and without Flex.

Examples of flexible parts

First, create a file called flexibility.dart.

touch flexible.dart

Copy the code

Next, paste the following code into the file.

class FlexibleWidget extends StatelessWidget { const FlexibleWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: GestureDetector( onTap: () { Navigator.pop(context); }, child: Icon(Icons.arrow_back_ios_new)), ), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Column( children: [ Text("Flexfit.loose"), Row( mainAxisAlignment:MainAxisAlignment.center, children: [ Flexible( flex: 1, fit: FlexFit.loose, child: Container( height: 100, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.deepOrange[400], ), child:Icon(Icons.backpack), ), ), SizedBox( width: 10, ), Flexible( flex: 1, fit: FlexFit.loose, child: Container( height: 100, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.deepOrange[400], ), child:Icon(Icons.backpack), ), ) ], ) ], ), Column( children: [ Text("Flexfit.tight"), Row( children: [ Flexible( flex: 1, fit: FlexFit.tight, child: Container( height: 100, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.purpleAccent, ), child:Icon(Icons.backpack), ), ), SizedBox( width: 10, ), Flexible( flex: 1, fit: FlexFit.tight, child: Container( height: 100, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.purpleAccent, ), child:Icon(Icons.backpack), ), ) ], ) ], ) ], ), ), ); }}Copy the code

In the code, we create a stateless widget, FlexibleWidget. Inside it, we create two lines of flexible widget content. On the first line, we use flexfit.loose, and on the second line, we use flexfit.tight. With this, the icon will fill the available space provided by the child.

The picture below shows such a layout, flexfit.loose, which uses the minimum space provided by the child, and Flexfit.Tight, which fills the available space provided by the child.

The difference between enlarged and flexible parts

As I pointed out earlier, the main difference between these widgets is their attributes. The expanded widget has only child and Flex attributes, which can be a limitation if misused. In contrast, flexible widgets have more attributes; This makes for flexible use, hence the name.

conclusion

In this article, we learned about responsive screen layouts using “extended” and “flexible” widgets. We started with an introduction to the potential problems that inevitably arise when creating responsive screen layouts using containers, and then introduced the solution: extensible and flexible widgets. We covered their properties, similarities, differences, and most importantly, a hands-on example. I hope this article has been helpful. Note that no practice, no learning, so keep practicing.

The postCreate responsive layouts with Flexible and Expanded widgets in Flutterappeared first onLogRocket Blog.