
Layout Widgets in Flutter
In Flutter, layout widgets play a key role in arranging and positioning other widgets on the screen. They help you build responsive, flexible, and visually organized user interfaces.
Type of LayoutWidgets
Layout widgets can be grouped into two distinct category based on its child:
1. Single-Child Layout Widgets
These widgets are designed to hold only one child. They’re perfect when you need to wrap a widget to control its position, add padding, alignment, or apply styling.Here are some commonly used single-child layout widgets:
Container
A versatile box that wraps a single widget. You can use it to apply padding, margins, borders, background color, and more.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Container Example'),
),
body: Center(
child: Container(
width: 200,
height: 100,
color: Colors.blue,
child: Center(
child: Text(
'Hello, Flutter!',
style: TextStyle(color: Colors.white),
),
),
),
),
),
);
}
}
Align
Aligns its child within itself based on the alignment you choose (e.g., topLeft, center, bottomRight, etc.).
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Align Widget Example'),
),
body: Center(
child: Align(
alignment: Alignment.topRight,
child: Text('Aligned text'),
),
),
),
);
}
}
Padding
Adds empty space around its child. This helps give breathing room between widgets, improving the visual layout.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Padding Example'),
),
body: Center(
child: Padding(
padding: EdgeInsets.all(16.0), // Adds padding on all sides
child: Container(
color: Colors.blue,
child: Text(
'Hello, Flutter!',
style: TextStyle(color: Colors.white, fontSize: 24),
),
),
),
),
),
);
}
}
Center
Places its child widget exactly at the center of the parent widget (both vertically and horizontally).
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Center Widget Example'),
),
body: Center(
child: Container(
color: Colors.orange,
width: 200,
height: 100,
child: Center(
child: Text(
'Centered Text',
style: TextStyle(color: Colors.white, fontSize: 24),
),
),
),
),
),
);
}
}
SizedBox
Creates a box with a specific width and height. It’s useful when you want fixed spacing or a fixed size for a widget.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('SizedBox Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
color: Colors.blue,
width: 100,
height: 100,
child: Center(child: Text('Box 1')),
),
SizedBox(height: 20), // Adds vertical space between the boxes
Container(
color: Colors.red,
width: 100,
height: 100,
child: Center(child: Text('Box 2')),
),
],
),
),
),
);
}
}
FractionallySizedBox
Sizes its child to a fraction of the available space. For example, if widthFactor: 0.5, the child will take up 50% of the width of its parent.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('FractionallySizedBox Example'),
),
body: Center(
child: FractionallySizedBox(
alignment: Alignment.center,
widthFactor: 0.5, // 50% of available width
heightFactor: 0.3, // 30% of available height
child: Container(
color: Colors.green,
child: Center(
child: Text(
'Half Width & 30% Height',
style: TextStyle(color: Colors.white),
),
),
),
),
),
),
);
}
}
Multiple Child Widgets
Multi-child layout widgets are used when a widget needs to manage and display more than one child widget. Each multi-child layout widget arranges its children in a unique way.
- Arranges its children horizontally, side by side.
- Arranges its children vertically, one on top of the other.
- Displays children as a scrollable list. Ideal for dynamic lists of data.
- Organizes children in a grid, like a gallery layout.
- Places children in a horizontal or vertical line and wraps them to the next line if there’s not enough space.
- Arranges widgets in a grid format using rows and columns. Great for displaying tabular data.
- Gives you total control by letting you define your own layout logic using a custom LayoutDelegate.
ListView
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('ListView Example'),
),
body: ListView(
children: [
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
ListTile(title: Text('Item 3')),
],
),
),
);
}
}
GridView
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('GridView Example'),
),
body: GridView.count(
crossAxisCount: 2, // Number of columns
children: [
Container(color: Colors.blue, child: Center(child: Text('Box 1'))),
Container(color: Colors.red, child: Center(child: Text('Box 2'))),
Container(color: Colors.green, child: Center(child: Text('Box 3'))),
Container(color: Colors.yellow, child: Center(child: Text('Box 4'))),
],
),
),
);
}
}
Wrap
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Wrap Example'),
),
body: Wrap(
spacing: 10.0, // Space between children horizontally
runSpacing: 10.0, // Space between lines
children: [
Chip(label: Text('Chip 1')),
Chip(label: Text('Chip 2')),
Chip(label: Text('Chip 3')),
Chip(label: Text('Chip 4')),
],
),
),
);
}
}
Table
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Table Example'),
),
body: Table(
border: TableBorder.all(color: Colors.black), // Adds borders
children: [
TableRow(children: [
Text('Header 1', textAlign: TextAlign.center),
Text('Header 2', textAlign: TextAlign.center),
Text('Header 3', textAlign: TextAlign.center),
]),
TableRow(children: [
Text('Row 1, Col 1'),
Text('Row 1, Col 2'),
Text('Row 1, Col 3'),
]),
],
),
),
);
}
}
CustomMultiChildLayout
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('CustomMultiChildLayout Example'),
),
body: CustomMultiChildLayout(
delegate: MyCustomLayoutDelegate(),
children: [
LayoutId(
id: 'box1',
child: Container(color: Colors.blue, width: 50, height: 50),
),
LayoutId(
id: 'box2',
child: Container(color: Colors.red, width: 100, height: 50),
),
],
),
),
);
}
}
class MyCustomLayoutDelegate extends MultiChildLayoutDelegate {
@override
void performLayout(Size size) {
if (hasChild('box1')) {
layoutChild('box1', BoxConstraints.loose(size));
positionChild('box1', Offset(0, 0));
}
if (hasChild('box2')) {
layoutChild('box2', BoxConstraints.loose(size));
positionChild('box2', Offset(60, 60));
}
}
@override
bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) => false;
}
Dashboard with Rows, Columns, and Cards
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Dashboard Layout'),
),
body: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildCard('Item 1', Colors.blue),
_buildCard('Item 2', Colors.red),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildCard('Item 3', Colors.green),
_buildCard('Item 4', Colors.orange),
],
),
],
),
),
);
}
Widget _buildCard(String title, Color color) {
return Card(
color: color,
child: Container(
width: 100,
height: 100,
child: Center(
child: Text(
title,
style: TextStyle(color: Colors.white),
),
),
),
);
}
}
2. Responsive Grid Layout
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Responsive Grid Layout'),
),
body: LayoutBuilder(
builder: (context, constraints) {
int crossAxisCount = constraints.maxWidth > 600 ? 4 : 2;
return GridView.count(
crossAxisCount: crossAxisCount,
children: List.generate(8, (index) {
return Container(
margin: EdgeInsets.all(8.0),
color: Colors.teal[100 * ((index % 8) + 1)],
child: Center(
child: Text('Item $index'),
),
);
}),
);
},
),
),
);
}
}
Custom Scroll View with Slivers
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: 200.0,
flexibleSpace: FlexibleSpaceBar(
title: Text('Sliver AppBar'),
background: Image.network(
'https://via.placeholder.com/300',
fit: BoxFit.cover,
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return ListTile(
title: Text('Item #$index'),
);
},
childCount: 20,
),
),
],
),
),
);
}
}