The Expanded widget is used within a Row, Column, or Flex to distribute available space among its children, either equally or proportionally using the flex property.
Responsive Flutter layout with Expanded widget
Key takeaways:
The
Expandedwidget in Flutter helps a child widget take up extra space within a layout. It stretches the child to fill available space in the direction you’re arranging the widgets (either horizontally or vertically).Wrapping a child widget with
Expandedallows it to occupy all available space or a specified proportion using theflexproperty.Without
flex, all children in anExpandedwidget share space equally. Addingflexvalues assigns space proportionally.The
Expandedwidget is versatile and can be used in both web and mobile applications.The
expandedWithFlex()andexpandedDefault()methods showcase howExpandedwidgets allocate space differently with and without flex values.
Responsive layouts are a cornerstone of modern app development, and Flutter makes this easier with the Expanded widget. This widget is designed to dynamically allocate space among child widgets within a Row or Column, making your app adaptable to different screen sizes. To customize how much space each widget occupies, you can use the flex property. This helps resolve any competition for space by assigning different proportions to the children. In this Answer, we’ll explore how the Expanded widget works through two examples: its default behavior and the use of the flex property to customize space distribution.
If you're eager to master Flutter layouts, dive into our Answer: Layouts in Flutter and unlock the secrets to building dynamic and responsive UIs.
Example 1: The default behavior of Expanded
The Expanded widget is a layout widget that can only have one child assigned to it. In the following example, the Row widget contains three children created using the childWidget() function, each wrapped in an Expanded widget. By default, all children expand equally to fill the available horizontal space, as the main axis is horizontal.
Row(children: [Expanded(child: Container(color: Colors.red,child: const Center(child: Text("Child 1")),),),Expanded(child: Container(color: Colors.green,child: const Center(child: Text("Child 2")),),),Expanded(child: Container(color: Colors.blue,child: const Center(child: Text("Child 3")),),),],)
This code creates a Row with three Expanded children, each sharing equal space within the row. Each child widget is wrapped in a container with a unique background color and a centered text label. The layout automatically distributes the available horizontal space evenly among the children.
Example 2: Customizing space with the flex property
In this example, each Expanded widget is provided with a flex value. This helps resolve any competition for space by specifying how much space each child should take relative to the others.
Row(children: [Expanded(flex: 4,child: Container(color: Colors.red,child: const Center(child: Text("Flex 4")),),),Expanded(flex: 3,child: Container(color: Colors.green,child: const Center(child: Text("Flex 3")),),),Expanded(flex: 1,child: Container(color: Colors.blue,child: const Center(child: Text("Flex 1")),),),],)
This code defines a Row with three Expanded children, each taking up space proportional to their flex values: 4, 3, and 1. The containers, with distinct colors and text labels, adjust their widths dynamically based on the assigned proportions, creating a responsive layout.
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 the ”Run” button to execute the application.
import 'package:flutter/material.dart';
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> {
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) {
dropDownValue = dropdown[newValue];
},
),
),
],
),
body: isFlex ? expandedWithFlex() : expandedDefault(),
);
}
Widget expandedWithFlex() {
return Row(
children: [
Expanded(
flex: 4,
child: Container(
color: Colors.red,
child: const Center(child: Text("Flex 4")),
),
),
Expanded(
flex: 3,
child: Container(
color: Colors.green,
child: const Center(child: Text("Flex 3")),
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.blue,
child: const Center(child: Text("Flex 1")),
),
),
],
);
}
Widget expandedDefault() {
return Row(
children: [
Expanded(
child: Container(
color: Colors.red,
child: const Center(child: Text("Child 1")),
),
),
Expanded(
child: Container(
color: Colors.green,
child: const Center(child: Text("Child 2")),
),
),
Expanded(
child: Container(
color: Colors.blue,
child: const Center(child: Text("Child 3")),
),
),
],
);
}
void updateContainer(int option) {
setState(() {
isFlex = option == withFlex;
});
}
}
Once the server is up and running, please open the app using the URL provided at “Your app can be found at.”
Explanation
Let’s understand how the code above works by breaking it down:
Line 1: We import the
package:flutter/material.dartpackage to use the pre-built design widgets for Flutter.Lines 5–13: We define a stateless widget class named
ExpandedDemothat returns aMaterialAppwidget in its build() method for building material design apps, such as a theme, navigation, and accessibility support.Lines 15–18: We define a stateful widget class named
MyExpandedthat can change its state during its lifetime.Lines 75–101: We defined an
expandedWithFlex()method that returns aRowwidget with threechildwidgets wrapped under anExpandedwidget. Each widget has a property set, which determines how much space it should occupy along the main axis of its parent widget.Lines 103–126: We defined an
expandedDefault()method that returns aRowwidget with three child widgets, which are wrapped under anExpandedwidget. Each widget is given achildwidget 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 theRow.
When to use the Expanded widget
Dynamic space allocation: Use the
Expandedwidget when you want child widgets within aRow,Column, orFlexto automatically expand and fill the available space along the main axis.Equal space distribution: It’s ideal when all child widgets share the space equally, making it great for simple, balanced layouts.
Quick layout adjustments: If you don’t need to customize the space allocation of each child,
Expandedprovides a quick solution for flexible layouts without too much complexity.
However, if you need more control over how much space each child occupies:
For more control: While
Expandedforces a child widget to take up all available space, theFlexiblewidget allows child widgets to take only as much space as they need while still being able to expand if space is available. Consider theFlexiblewidget, which allows you to assign specific proportions of space to child widgets, offering more flexibility compared toExpanded.Granular adjustments: Use
Flexiblewhen you need child widgets to share space in a non-equal way, based on their assignedflexvalues.
Best practices for the Expanded widget
Combine with other widgets: Use
ExpandedwithFlexibleorSpacerwidgets for more control over spacing and layout.Keep it simple: Avoid overcomplicating designs with nested
Expandedwidgets.Test on different screens: Always test your layout on various devices to ensure responsiveness.
Benefits of using Expanded widget
Automatic space distribution: Adjusts child sizes dynamically based on available space.
Cleaner layouts: Simplifies the process of creating flexible, adaptable designs.
Code efficiency: Reduces the need for manual size calculations.
Conclusion
The Expanded widget in Flutter is a powerful tool for creating responsive layouts by distributing available space among child widgets within a Row or Column. By using the flex property, developers can control how much space each child occupies, enabling precise and flexible design adjustments. This functionality makes the Expanded widget essential for building adaptable user interfaces in both web and mobile Flutter applications. Through examples and practical implementation, this Answer highlights how to effectively utilize Expanded widgets to achieve dynamic and proportional layouts.
Unlock your full potential with our comprehensive course: Beginning Flutter: Android Mobile App Development. Dive deeper into the topic and gain hands-on experience through expert-led lessons.
Frequently asked questions
Haven’t found what you were looking for? Contact Us