Responsive Flutter layout with Expanded widget

The Expanded widget is a single child layout widget, which means it can only have one child assigned to it. In this example, the Row widget has three children built using childWidget(). Each of the children is wrapped in the Expanded widget. All children expand themselves in the direction of the main-axis, which is horizontal in this case. However, a value for flex property can be provided to resolve any competition for space. In the second example below, each Expanded widget is provided with a flex value.

Using the Expanded widget

Let’s look at the following code to understand how to use the Expanded widget.

Row(
   children: [
     Expanded(
       child: childWidget(""),
     ),
     Expanded(
       child: childWidget(""),
     ),
     Expanded(
       child: childWidget(""),
     ),
   ],
 )

Using the Expanded widget (flex property)

Let’s look at the following code to understand how to use the Expanded widget with flex property.

Row(
   children: [
     Expanded(
       flex: 4,
       child: childWidget("4/8"),
     ),
     Expanded(
       flex: 3,
       child: childWidget("3/8"),
     ),
     Expanded(
       flex: 1,
       child: childWidget("1/8"),
     ),
   ],
 )

Source code

Note: We can use this code for both web and android applications. But in this section, we are only using the flutter web application for the visual demonstration.

Click on the "Run" button to execute the application.

import 'package:flutter/material.dart';

/// Single child layout widget

/// Expanded widget allows child of Row, Column,
/// or Flex widgets expand to fill the available space along
/// the main axis of parent widget.
void main() => runApp(ExpandedDemo());

class ExpandedDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MyExpanded(),
    );
  }
}

class MyExpanded extends StatefulWidget {
  @override
  _MyExpandedState createState() => _MyExpandedState();
}

int noFlex = 0;
int withFlex = 1;

Map<int, String> dropdown = {
  noFlex: "No `flex` Property",
  withFlex: 'Using `flex`',
};

class _MyExpandedState extends State<MyExpanded> {
  @override
  void didUpdateWidget(MyExpanded oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  int _currentOption = 0;
  String dropDownValue = dropdown[0];
  bool isFlex = false;

  @override
  void initState() {
    super.initState();
    updateContainer(0);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Expanded Widget"),
          actions: [
            Padding(
              padding: const EdgeInsets.only(left: 16.0),
              child: DropdownButton(
                hint: dropDownValue == null
                    ? Text('Select')
                    : Text(dropDownValue),
                items: dropdown.keys
                    .map((e) => DropdownMenuItem(
                          child: Text(dropdown[e]),
                          onTap: () {
                            setState(() {
                              _currentOption = e;

                              updateContainer(
                                  _currentOption == 0 ? noFlex : withFlex);
                            });
                          },
                          value: e,
                        ))
                    .toList(),
                onChanged: (newValue) {
                  print(newValue);
                  dropDownValue = dropdown[newValue];
                },
              ),
            )
          ],
        ),
        //Expanded Widget Usage
        body: isFlex ? expandedWithFlex() : expandedDefault());
  }

  Widget expandedWithFlex() {
    return Row(
      children: [
        Expanded(
          flex: 4,
          child: childWidget("4/8"),
        ),
        Expanded(
          flex: 3,
          child: childWidget("3/8"),
        ),
        Expanded(
          flex: 1,
          child: childWidget("1/8"),
        ),
      ],
    );
  }

  Widget expandedDefault() {
    return Row(
      children: [
        Expanded(
          child: childWidget(""),
        ),
        Expanded(
          child: childWidget(""),
        ),
        Expanded(
          child: childWidget(""),
        ),
      ],
    );
  }

  Widget childWidget(String text) {
    return Container(
      width: 100,
      height: 100,
      decoration: BoxDecoration(
        image: const DecorationImage(
          image: AssetImage('assets/flutter_icon.png'),
          fit: BoxFit.cover,
        ),
        border: Border.all(
          color: Colors.black,
          width: 3,
        ),
      ),
      child: Text(text),
    );
  }

  void updateContainer(int option) {
    switch (option) {
      case 0:
        setState(() {
          isFlex = false;
        });
        break;
      case 1:
        setState(() {
          isFlex = true;
        });
        break;
    }
  }
}
Using Expanded widget

Explanation

Let’s understand how the code above works by breaking it down:

  • Line 1: We import the package:flutter/material.dart package to use the pre-built design widgets for flutter.

  • Lines 10–18: We define a stateless widget class named ExpandedDemo that returns a MaterialApp widget in its build() method for building material design apps, such as a theme, navigation, and accessibility support.

  • Lines 20–23: We define a stateful widget class named MyExpanded that can change its state during its lifetime.

  • Lines 87–104: We defined an expandedWithFlex() method that returns a Row widget with three child widgets wrapped under an Expanded widget. Each widget has a property set, which determines how much space it should occupy along the main axis of its parent widget.

  • Lines 106–120: We defined an expandedDefault() method that returns a Row widget with three child widgets, which are wrapped under an Expanded widget. Each widget is given a child widget by calling the function with an empty string as the argument. The widget allows the child widget to expand and fill the available space along the main axis of the Row.

Free Resources

Copyright ©2024 Educative, Inc. All rights reserved