Widget Overview

Understanding Flutter's building blocks

🧩 What are Widgets?

Widgets are the building blocks of Flutter apps. Everything you see on screen is a widget - buttons, text, images, layouts. Widgets describe what the UI should look like based on their configuration. After return you can add one widgets with "child:" attribute, and many widgets with "children:" attribute.


// Simple widget example
Text('Hello Flutter!')

// Widget with styling
Container(
  child: Text('Styled Text'),
)
                                    

Widget Types

📦

Stateless

Widgets that don't change

class MyWidget extends
StatelessWidget {}
🔄

Stateful

Widgets that can change

class MyWidget extends
StatefulWidget {}
📐

Layout

Arrange other widgets

Column, Row,
Stack, Container
🎨

UI Elements

Visual components

Text, Image,
Icon, Button

🔹 Stateless Widgets

Widgets that don't change over time:

import 'package:flutter/material.dart';

// Stateless widget - immutable
class WelcomeScreen extends StatelessWidget {
  final String userName;
  
  // Constructor
  WelcomeScreen({required this.userName});
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Welcome'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(
              Icons.person,
              size: 100,
              color: Colors.blue,
            ),
            SizedBox(height: 20),
            Text(
              'Hello, $userName!',
              style: TextStyle(fontSize: 24),
            ),
            Text(
              'Welcome to Flutter',
              style: TextStyle(fontSize: 16, color: Colors.grey),
            ),
          ],
        ),
      ),
    );
  }
}

// Usage
void main() {
  runApp(MaterialApp(
    home: WelcomeScreen(userName: 'John'),
  ));
}

🔹 Stateful Widgets

Widgets that can change and rebuild:

import 'package:flutter/material.dart';

// Stateful widget - can change
class CounterWidget extends StatefulWidget {
  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State {
  int counter = 0; // Mutable state
  
  void incrementCounter() {
    setState(() {
      counter++; // Update state and rebuild
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Counter App'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'You pressed the button:',
              style: TextStyle(fontSize: 20),
            ),
            Text(
              '$counter',
              style: TextStyle(
                fontSize: 48,
                fontWeight: FontWeight.bold,
                color: Colors.blue,
              ),
            ),
            SizedBox(height: 20),
            Text(
              counter == 0 ? 'Start clicking!' : 'Keep going!',
              style: TextStyle(fontSize: 16, color: Colors.grey),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: incrementCounter,
        child: Icon(Icons.add),
        tooltip: 'Increment',
      ),
    );
  }
}

🔹 Common Layout Widgets

Widgets for arranging other widgets:

🔸 Column (Vertical Layout)

Column(
  mainAxisAlignment: MainAxisAlignment.center,
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Text('First'),
    Text('Second'),
    Text('Third'),
  ],
)

🔸 Row (Horizontal Layout)

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Icon(Icons.star),
    Icon(Icons.star),
    Icon(Icons.star),
  ],
)

🔸 Container (Box with Styling)

Container(
  width: 200,
  height: 100,
  padding: EdgeInsets.all(16),
  margin: EdgeInsets.all(8),
  decoration: BoxDecoration(
    color: Colors.blue,
    borderRadius: BorderRadius.circular(12),
    boxShadow: [
      BoxShadow(
        color: Colors.grey,
        blurRadius: 5,
        offset: Offset(2, 2),
      ),
    ],
  ),
  child: Text(
    'Styled Container',
    style: TextStyle(color: Colors.white),
  ),
)

🔸 Stack (Overlapping Widgets)

Stack(
  children: [
    Container(
      width: 200,
      height: 200,
      color: Colors.blue,
    ),
    Positioned(
      top: 50,
      left: 50,
      child: Text(
        'Overlaid Text',
        style: TextStyle(color: Colors.white, fontSize: 20),
      ),
    ),
  ],
)

🔹 Common UI Widgets

Essential widgets for building interfaces:

🔸 Text Widget

Text(
  'Hello Flutter!',
  style: TextStyle(
    fontSize: 24,
    fontWeight: FontWeight.bold,
    color: Colors.blue,
    letterSpacing: 2,
    decoration: TextDecoration.underline,
  ),
  textAlign: TextAlign.center,
  maxLines: 2,
  overflow: TextOverflow.ellipsis,
)

🔸 Image Widget

// From network
Image.network(
  'https://example.com/image.jpg',
  width: 200,
  height: 200,
  fit: BoxFit.cover,
)

// From assets
Image.asset(
  'assets/images/logo.png',
  width: 100,
  height: 100,
)

🔸 Button Widgets

// Elevated Button
ElevatedButton(
  onPressed: () {
    print('Button pressed!');
  },
  child: Text('Click Me'),
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.blue,
    padding: EdgeInsets.symmetric(horizontal: 30, vertical: 15),
  ),
)

// Text Button
TextButton(
  onPressed: () {},
  child: Text('Text Button'),
)

// Icon Button
IconButton(
  icon: Icon(Icons.favorite),
  onPressed: () {},
  color: Colors.red,
  iconSize: 30,
)

🔸 TextField Widget

TextField(
  decoration: InputDecoration(
    labelText: 'Enter your name',
    hintText: 'John Doe',
    prefixIcon: Icon(Icons.person),
    border: OutlineInputBorder(),
  ),
  onChanged: (value) {
    print('Input: $value');
  },
)

🔹 Scaffold Widget

The basic structure for Material Design apps:

Scaffold(
  appBar: AppBar(
    title: Text('My App'),
    actions: [
      IconButton(
        icon: Icon(Icons.search),
        onPressed: () {},
      ),
      IconButton(
        icon: Icon(Icons.more_vert),
        onPressed: () {},
      ),
    ],
  ),
  body: Center(
    child: Text('Main Content'),
  ),
  floatingActionButton: FloatingActionButton(
    onPressed: () {},
    child: Icon(Icons.add),
  ),
  drawer: Drawer(
    child: ListView(
      children: [
        DrawerHeader(
          child: Text('Menu'),
          decoration: BoxDecoration(color: Colors.blue),
        ),
        ListTile(
          leading: Icon(Icons.home),
          title: Text('Home'),
          onTap: () {},
        ),
        ListTile(
          leading: Icon(Icons.settings),
          title: Text('Settings'),
          onTap: () {},
        ),
      ],
    ),
  ),
  bottomNavigationBar: BottomNavigationBar(
    items: [
      BottomNavigationBarItem(
        icon: Icon(Icons.home),
        label: 'Home',
      ),
      BottomNavigationBarItem(
        icon: Icon(Icons.search),
        label: 'Search',
      ),
      BottomNavigationBarItem(
        icon: Icon(Icons.person),
        label: 'Profile',
      ),
    ],
  ),
)

🔹 ListView Widget

Display scrollable lists:

// Simple ListView
ListView(
  children: [
    ListTile(
      leading: Icon(Icons.person),
      title: Text('John Doe'),
      subtitle: Text('Software Developer'),
      trailing: Icon(Icons.arrow_forward),
      onTap: () {},
    ),
    ListTile(
      leading: Icon(Icons.person),
      title: Text('Jane Smith'),
      subtitle: Text('Designer'),
      trailing: Icon(Icons.arrow_forward),
      onTap: () {},
    ),
  ],
)

// ListView.builder (for large lists)
ListView.builder(
  itemCount: 100,
  itemBuilder: (context, index) {
    return ListTile(
      leading: CircleAvatar(
        child: Text('${index + 1}'),
      ),
      title: Text('Item $index'),
      subtitle: Text('Description for item $index'),
    );
  },
)

🔹 GridView Widget

Display items in a grid:

GridView.count(
  crossAxisCount: 2, // 2 columns
  crossAxisSpacing: 10,
  mainAxisSpacing: 10,
  padding: EdgeInsets.all(10),
  children: [
    Container(
      color: Colors.red,
      child: Center(child: Text('1')),
    ),
    Container(
      color: Colors.blue,
      child: Center(child: Text('2')),
    ),
    Container(
      color: Colors.green,
      child: Center(child: Text('3')),
    ),
    Container(
      color: Colors.orange,
      child: Center(child: Text('4')),
    ),
  ],
)

🔹 Complete Widget Example

Putting it all together:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Widget Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State {
  int selectedIndex = 0;
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Widget Overview'),
        actions: [
          IconButton(
            icon: Icon(Icons.search),
            onPressed: () {},
          ),
        ],
      ),
      body: Column(
        children: [
          Container(
            padding: EdgeInsets.all(16),
            color: Colors.blue[50],
            child: Row(
              children: [
                Icon(Icons.info, color: Colors.blue),
                SizedBox(width: 10),
                Expanded(
                  child: Text(
                    'Welcome to Flutter Widgets!',
                    style: TextStyle(fontSize: 16),
                  ),
                ),
              ],
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: 10,
              itemBuilder: (context, index) {
                return Card(
                  margin: EdgeInsets.all(8),
                  child: ListTile(
                    leading: CircleAvatar(
                      child: Text('${index + 1}'),
                    ),
                    title: Text('Widget ${index + 1}'),
                    subtitle: Text('Tap to learn more'),
                    trailing: Icon(Icons.arrow_forward_ios),
                    onTap: () {
                      ScaffoldMessenger.of(context).showSnackBar(
                        SnackBar(
                          content: Text('Tapped Widget ${index + 1}'),
                        ),
                      );
                    },
                  ),
                );
              },
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: Icon(Icons.add),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: selectedIndex,
        onTap: (index) {
          setState(() {
            selectedIndex = index;
          });
        },
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.favorite),
            label: 'Favorites',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
      ),
    );
  }
}

🔹 Widget Tree Concept

Understanding how widgets nest:

MaterialApp
└── Scaffold
    ├── AppBar
    │   └── Text
    ├── Body
    │   └── Column
    │       ├── Container
    │       │   └── Text
    │       ├── Row
    │       │   ├── Icon
    │       │   └── Text
    │       └── ElevatedButton
    │           └── Text
    └── FloatingActionButton
        └── Icon

// Each widget can have children
// Children are also widgets
// This creates a tree structure

🧠 Test Your Knowledge

Which widget is used for widgets that can change?