Layout Widgets in Flutter
In Flutter, layout widgets are used to arrange and position child widgets on the screen. Here are the main types of layout widgets you can use to create flexible, responsive, and organized UI:
Type of LayoutWidgets
Layout widgets can be grouped into two distinct category based on its child:
1. Single-Child Layout Widgets
These widgets can hold only one child widget and are useful for adding padding, margins, alignment, or decoration to the child widget.
Container
A box that can contain a single widget and allows you to customize its size, padding, margin, decoration, 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('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 provided alignment.
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
The Padding widget in Flutter is used to add empty space around its child widget. It helps in adjusting the space around a widget, making the UI look cleaner and more organized.
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
The Center widget in Flutter is used to align its child widget in the center of the available space. It places its child widget both vertically and horizontally at the center of the parent 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('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
The SizedBox widget is used to create a box with a specific width and height. It is often used to add fixed space between widgets, as well as to specify the size of 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
The FractionallySizedBox widget sizes its child to a fraction of the available space. You can define the width and height factor, which is a value between 0.0 and 1.0, where 1.0 means the full width or height.
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
In this category, a given widget will have more than one child widgets and the layout of each widget is unique. For example, Row widget allows the laying out of its children in horizontal direction,whereas Column widget allows laying out of its children in vertical direction. By composing Row and Column, widget with any level of complexity can be built. Let us learn some of the frequently used widgets in this section.
- Row - Allows to arrange its children in a horizontal manner.
- Column - Allows to arrange its children in a vertical manner.
- ListView - Allows to arrange its children as list.
- GridView - Allows to arrange its children as gallery.
- Wrap- A widget that arranges its children in a line but wraps them to the next line when there’s no available space.
- Table- A grid-like layout that arranges children in rows and columns.
- CustomMultiChildLayout-Allows you to create custom layouts by positioning each child using a Delegate.
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,
),
),
],
),
),
);
}
}