Flutter Layout Widgets


Basic file setup

Create a new Flutter project or open an existing one. We will add examples of each button in the main.dart file.

import 'package:flutter/material.dart';

void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body:  Center(
          child: //add code here
        )
        ),
      );
  }
}

StackWidget

The Stack widget overlays its children on top of each other.

StackExample.dart file

class StackExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Stack(
        alignment: Alignment.center,
        children: [
          Container(width: 200, height: 200, color: Colors.blue),
          Container(width: 150, height: 150, color: Colors.green),
          Container(width: 100, height: 100, color: Colors.red),
        ],
      ),
    );
  }
}

main.dart file

import 'package:flutter/material.dart';
import 'package:basic_widgets/StackExample.dart';
void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body:  Center(
          child: StackExample()
        )
        ),
      );
  }
}

Key Points:

  • The largest container is at the bottom, and the smallest is on top.
  • Use the alignment property to position widgets within the Stack.

GridView

The GridView widget displays widgets in a grid format.

GridViewExample.dart file

class GridViewExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GridView.count(
      crossAxisCount: 3,
      crossAxisSpacing: 10,
      mainAxisSpacing: 10,
      padding: EdgeInsets.all(10),
      children: List.generate(9, (index) {
        return Container(
          color: Colors.blueAccent,
          child: Center(
            child: Text(
              "Item ${index + 1}",
              style: TextStyle(color: Colors.white),
            ),
          ),
        );
      }),
    );
  }
}

main.dart file

import 'package:flutter/material.dart';
import 'package:basic_widgets/GridViewExample.dart';
void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body:  Center(
          child: GridViewExample()
        )
        ),
      );
  }
}

Key Points:

  • Use GridView.count for a fixed number of columns.
  • Customize spacing with crossAxisSpacing and mainAxisSpacing.

ListView Widget

The ListView widget creates a scrollable list.

ListViewExample.dart file

class ListViewExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: EdgeInsets.all(10),
      children: List.generate(10, (index) {
        return Container(
          margin: EdgeInsets.symmetric(vertical: 5),
          color: Colors.lightBlue,
          child: ListTile(
            title: Text("Item ${index + 1}"),
          ),
        );
      }),
    );
  }
}

main.dart file

import 'package:flutter/material.dart';
import 'package:basic_widgets/ListViewExample.dart';
void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body:  Center(
          child: ListViewExample()
        )
        ),
      );
  }
}

Key Points:

  • ListView is useful for displaying vertically scrollable lists.
  • Combine with ListTile for standardized row layouts.

ListTile Example

The ListTile widget is ideal for creating rows with leading, title, subtitle, and trailing widgets.

ListTileExample.dart file

class ListTileExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: EdgeInsets.all(10),
      children: [
        ListTile(
          leading: Icon(Icons.person),
          title: Text("John Doe"),
          subtitle: Text("Software Developer"),
          trailing: Icon(Icons.arrow_forward),
          onTap: () {
            print("Tapped on John Doe");
          },
        ),
        ListTile(
          leading: Icon(Icons.person),
          title: Text("Jane Smith"),
          subtitle: Text("UI/UX Designer"),
          trailing: Icon(Icons.arrow_forward),
          onTap: () {
            print("Tapped on Jane Smith");
          },
        ),
      ],
    );
  }
}

main.dart file

import 'package:flutter/material.dart';
import 'package:basic_widgets/ListTileExample.dart';
void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body:  Center(
          child: ListTileExample()
        )
        ),
      );
  }
}

Key Points:

  • Use onTap to handle row taps.
  • Add leading for icons, trailing for actions, and subtitle for additional information.

Table Widget

The Table widget arranges children in rows and columns.

TableExample.dart file

class TableExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Table(
      border: TableBorder.all(),
      children: [
        TableRow(children: [
          Padding(
            padding: EdgeInsets.all(8.0),
            child: Text("Name", style: TextStyle(fontWeight: FontWeight.bold)),
          ),
          Padding(
            padding: EdgeInsets.all(8.0),
            child: Text("Role", style: TextStyle(fontWeight: FontWeight.bold)),
          ),
        ]),
        TableRow(children: [
          Padding(
            padding: EdgeInsets.all(8.0),
            child: Text("John Doe"),
          ),
          Padding(
            padding: EdgeInsets.all(8.0),
            child: Text("Developer"),
          ),
        ]),
        TableRow(children: [
          Padding(
            padding: EdgeInsets.all(8.0),
            child: Text("Jane Smith"),
          ),
          Padding(
            padding: EdgeInsets.all(8.0),
            child: Text("Designer"),
          ),
        ]),
      ],
    );
  }
}

main.dart file

import 'package:flutter/material.dart';
import 'package:basic_widgets/TableExample.dart';
void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body:  Center(
          child: TableExample()
        )
        ),
      );
  }
}

Wrap Widget

The Wrap widget arranges children in multiple lines when there isn’t enough horizontal space.

WrapExample.dart file

class WrapExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Wrap(
      spacing: 10,
      runSpacing: 10,
      children: List.generate(10, (index) {
        return Container(
          width: 80,
          height: 80,
          color: Colors.purpleAccent,
          child: Center(
            child: Text(
              "Item ${index + 1}",
              style: TextStyle(color: Colors.white),
            ),
          ),
        );
      }),
    );
  }
}

main.dart file

import 'package:flutter/material.dart';
import 'package:basic_widgets/WrapExample.dart';
void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body:  Center(
          child: WrapExample()
        )
        ),
      );
  }
}

Key Points:

  • Use spacing for horizontal spacing and runSpacing for vertical spacing.
  • Wrap is perfect for dynamic layouts like tag clouds or grids.

IndexStack Widget

The IndexedStack widget displays only one child at a time based on an index.

IndexStackExample.dart file

class IndexedStackExample extends StatefulWidget {
  @override
  _IndexedStackExampleState createState() => _IndexedStackExampleState();
}

class _IndexedStackExampleState extends State<IndexedStackExample> {
  int _currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        IndexedStack(
          index: _currentIndex,
          children: [
            Container(width: 200, height: 200, color: Colors.red),
            Container(width: 200, height: 200, color: Colors.green),
            Container(width: 200, height: 200, color: Colors.blue),
          ],
        ),
        SizedBox(height: 20),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: List.generate(3, (index) {
            return ElevatedButton(
              onPressed: () {
                setState(() {
                  _currentIndex = index;
                });
              },
              child: Text("Show ${index + 1}"),
            );
          }),
        ),
      ],
    );
  }
}

main.dart file

import 'package:flutter/material.dart';
import 'package:basic_widgets/IndexStackExample.dart';
void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body:  Center(
          child: IndexedStackExample()
        )
        ),
      );
  }
}

Key Points:

  • Only the widget at the current index is displayed.
  • Great for tabbed interfaces or content switching.

All Components in ScrollView

main.dart file

import 'package:flutter/material.dart';
import 'package:basic_widgets/IndexStackExample.dart';
import 'package:basic_widgets/StackExample.dart';
import 'package:basic_widgets/GridViewExample.dart';
import 'package:basic_widgets/ListViewExample.dart';
import 'package:basic_widgets/ListTileExample.dart';
import 'package:basic_widgets/TableExample.dart';
import 'package:basic_widgets/WrapExample.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Flutter Layout Widgets")),
        body: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Text("Stack Example", textAlign: TextAlign.center),
              StackExample(),
              Divider(),
              Text("GridView Example", textAlign: TextAlign.center),
              Container(height: 200, child: GridViewExample()),
              Divider(),
              Text("ListView Example", textAlign: TextAlign.center),
              Container(height: 200, child: ListViewExample()),
              Divider(),
              Text("ListTile Example", textAlign: TextAlign.center),
              Container(height: 200, child: ListTileExample()),
              Divider(),
              Text("Table Example", textAlign: TextAlign.center),
              TableExample(),
              Divider(),
              Text("Wrap Example", textAlign: TextAlign.center),
              WrapExample(),
              Divider(),
              Text("IndexedStack Example", textAlign: TextAlign.center),
              IndexedStackExample(),
            ],
          ),
        ),
      ),
    );
  }
}

Each widget is displayed in a scrollable layout to make it easier to see the effects and interact with them. Use this tutorial to build layouts using Flutter’s versatile widgets!