Flutter Widgets

Flutter widgets operate on a declarative programming model where you describe what the UI should look like rather than imperatively changing it. This widget-based approach makes Flutter applications highly performant and maintainable, as Flutter widgets efficiently rebuild only when necessary through Flutter’s reactive framework.

Understanding Flutter Widget Types

Flutter widgets are categorized into two main types: StatelessWidget and StatefulWidget. These Flutter widget types determine how your widgets manage data and respond to changes in your application.

StatelessWidget in Flutter

StatelessWidget represents Flutter widgets that don’t maintain any internal state. These Flutter widgets are immutable, meaning their properties cannot change once created. StatelessWidget is perfect for static UI elements that display information without user interaction.

class MyStatelessWidget extends StatelessWidget {
  final String title;
  
  const MyStatelessWidget({Key? key, required this.title}) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return Text(title);
  }
}

The build method in StatelessWidget returns other Flutter widgets that describe the UI. This method gets called whenever the widget needs to be rendered, making StatelessWidget efficient for simple display purposes.

StatefulWidget in Flutter

StatefulWidget represents Flutter widgets that maintain mutable state throughout their lifecycle. These Flutter widgets can change their appearance in response to user interactions or data changes, making them essential for interactive UI components.

class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _counter = 0;
  
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Counter: $_counter'),
        ElevatedButton(
          onPressed: _incrementCounter,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

StatefulWidget uses the setState method to trigger rebuilds when the widget’s state changes. This mechanism ensures that Flutter widgets update efficiently while maintaining optimal performance.

Essential Flutter Layout Widgets

Flutter layout widgets provide the structure for organizing other Flutter widgets within your application. These Flutter widgets control positioning, sizing, and alignment of child widgets.

Container Widget

Container is one of the most versatile Flutter widgets, combining several layout and decoration properties into a single widget. Container widgets can handle padding, margins, borders, background colors, and transformations.

Container(
  width: 200,
  height: 100,
  padding: EdgeInsets.all(16),
  margin: EdgeInsets.symmetric(vertical: 8),
  decoration: BoxDecoration(
    color: Colors.blue,
    borderRadius: BorderRadius.circular(12),
    border: Border.all(color: Colors.white, width: 2),
  ),
  child: Text('Container Widget'),
)

Container widgets automatically size themselves to fit their child if no explicit dimensions are provided. When no child is present, Container widgets expand to fill available space.

Row and Column Widgets

Row and Column are fundamental Flutter layout widgets that arrange children horizontally and vertically respectively. These Flutter widgets use Flex properties to control how children are distributed within the available space.

// Row widget example
Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    Icon(Icons.home),
    Text('Home'),
    Icon(Icons.settings),
  ],
)

// Column widget example
Column(
  mainAxisAlignment: MainAxisAlignment.start,
  crossAxisAlignment: CrossAxisAlignment.stretch,
  children: [
    Text('Header'),
    Expanded(child: Text('Content')),
    Text('Footer'),
  ],
)

Row and Column Flutter widgets use MainAxisAlignment to control alignment along their primary axis and CrossAxisAlignment for the perpendicular axis. These properties give you precise control over widget positioning.

Stack Widget

Stack widget allows overlapping Flutter widgets, creating layered layouts where children can be positioned relative to the stack’s edges. Stack widgets are essential for creating complex UI designs with overlapping elements.

Stack(
  alignment: Alignment.center,
  children: [
    Container(
      width: 200,
      height: 200,
      color: Colors.red,
    ),
    Positioned(
      top: 20,
      right: 20,
      child: Icon(Icons.favorite, color: Colors.white),
    ),
    Text('Overlaid Text', style: TextStyle(color: Colors.white)),
  ],
)

Stack widgets use Positioned widgets to place children at specific locations. When children aren’t wrapped in Positioned, they’re centered by default or positioned according to the alignment property.

Interactive Flutter Widgets

Interactive Flutter widgets respond to user input and gestures, forming the foundation of user engagement in Flutter applications. These Flutter widgets handle touches, taps, and other user interactions.

Button Widgets

Flutter provides several button widgets for different use cases. ElevatedButton, TextButton, and OutlinedButton are the primary Flutter button widgets, each with distinct visual styles and use cases.

// ElevatedButton with elevated appearance
ElevatedButton(
  onPressed: () {
    print('Elevated button pressed');
  },
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.blue,
    foregroundColor: Colors.white,
    padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
  ),
  child: Text('Elevated Button'),
)

// TextButton for flat appearance
TextButton(
  onPressed: () {
    print('Text button pressed');
  },
  child: Text('Text Button'),
)

// OutlinedButton with border
OutlinedButton(
  onPressed: () {
    print('Outlined button pressed');
  },
  child: Text('Outlined Button'),
)

Button Flutter widgets accept an onPressed callback that defines the action when tapped. Setting onPressed to null disables the button, providing automatic visual feedback for disabled states.

TextField Widget

TextField is a crucial Flutter widget for text input, allowing users to enter and edit text. TextField widgets support various input types, validation, and formatting options.

class TextFieldExample extends StatefulWidget {
  @override
  _TextFieldExampleState createState() => _TextFieldExampleState();
}

class _TextFieldExampleState extends State<TextFieldExample> {
  final TextEditingController _controller = TextEditingController();
  
  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: _controller,
      decoration: InputDecoration(
        labelText: 'Enter your name',
        hintText: 'John Doe',
        border: OutlineInputBorder(),
        prefixIcon: Icon(Icons.person),
      ),
      onChanged: (value) {
        print('Text changed: $value');
      },
    );
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

TextField widgets use TextEditingController to manage text input and retrieve values. The decoration property allows customization of appearance, including labels, hints, and icons.

Display Flutter Widgets

Display Flutter widgets present information to users without requiring interaction. These Flutter widgets handle text, images, and other content presentation.

Text Widget

Text widget is the most basic Flutter widget for displaying textual content. Text widgets support styling, formatting, and various text properties for customizable text presentation.

Text(
  'This is a Text widget',
  style: TextStyle(
    fontSize: 18,
    fontWeight: FontWeight.bold,
    color: Colors.blue,
    fontFamily: 'Roboto',
  ),
  textAlign: TextAlign.center,
  maxLines: 2,
  overflow: TextOverflow.ellipsis,
)

Text Flutter widgets use TextStyle for styling and support properties like textAlign for alignment and overflow handling for long text. These properties ensure text displays correctly across different screen sizes.

Image Widget

Image widget displays images from various sources including assets, network, and files. Image Flutter widgets provide loading states, error handling, and sizing options.

// Image from assets
Image.asset(
  'assets/images/flutter_logo.png',
  width: 100,
  height: 100,
  fit: BoxFit.cover,
)

// Image from network
Image.network(
  'https://flutter.dev/images/flutter-logo-sharing.png',
  loadingBuilder: (context, child, loadingProgress) {
    if (loadingProgress == null) return child;
    return CircularProgressIndicator();
  },
  errorBuilder: (context, error, stackTrace) {
    return Icon(Icons.error);
  },
)

Image widgets support different BoxFit values to control how images are scaled within their containers. Network images automatically handle loading and error states.

Icon Widget

Icon widget displays material design icons and custom icon fonts. Icon Flutter widgets are vector-based, ensuring crisp appearance at any size while maintaining small file sizes.

Icon(
  Icons.favorite,
  size: 24,
  color: Colors.red,
)

// Custom icon
Icon(
  IconData(0xe900, fontFamily: 'CustomIcons'),
  size: 32,
  color: Colors.blue,
)

Icon Flutter widgets scale perfectly and support color customization. Material Design icons are included by default, while custom icons require font family specification.

Scrollable Flutter Widgets

Scrollable Flutter widgets handle content that exceeds screen dimensions, providing smooth scrolling experiences. These Flutter widgets are essential for displaying large amounts of content.

ListView Widget

ListView is a scrollable Flutter widget that displays children in a linear arrangement. ListView widgets efficiently render only visible items, making them perfect for large datasets.

ListView(
  padding: EdgeInsets.all(16),
  children: [
    ListTile(
      leading: Icon(Icons.person),
      title: Text('John Doe'),
      subtitle: Text('Software Developer'),
      trailing: Icon(Icons.arrow_forward),
    ),
    ListTile(
      leading: Icon(Icons.person),
      title: Text('Jane Smith'),
      subtitle: Text('UI Designer'),
      trailing: Icon(Icons.arrow_forward),
    ),
  ],
)

ListView widgets support various constructors including ListView.builder for dynamic content generation. The builder constructor creates items on-demand, optimizing memory usage for large lists.

GridView Widget

GridView displays Flutter widgets in a grid layout with configurable columns and spacing. GridView widgets are ideal for displaying collections of similar items like photos or products.

GridView.count(
  crossAxisCount: 2,
  padding: EdgeInsets.all(16),
  mainAxisSpacing: 16,
  crossAxisSpacing: 16,
  children: List.generate(20, (index) {
    return Container(
      decoration: BoxDecoration(
        color: Colors.blue[100],
        borderRadius: BorderRadius.circular(8),
      ),
      child: Center(
        child: Text('Item $index'),
      ),
    );
  }),
)

GridView Flutter widgets automatically handle item sizing and spacing. Different constructors like GridView.builder provide dynamic grid generation for large datasets.

Navigation Flutter Widgets

Navigation Flutter widgets manage screen transitions and routing within Flutter applications. These Flutter widgets provide the foundation for multi-screen apps and complex navigation patterns.

Navigator Widget

Navigator manages a stack of routes, enabling screen transitions and back navigation. Navigator Flutter widgets handle route management and provide methods for navigation control.

// Navigation to new screen
Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => SecondScreen(),
  ),
);

// Navigation with data
Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => DetailScreen(data: 'Sample data'),
  ),
);

// Pop current screen
Navigator.pop(context);

Navigator Flutter widgets maintain navigation history and support various transition animations. Routes can pass data between screens and return results to previous screens.

AppBar Widget

AppBar provides a material design app bar with title, actions, and navigation elements. AppBar Flutter widgets integrate with Scaffold to provide consistent navigation patterns.

AppBar(
  title: Text('My App'),
  backgroundColor: Colors.blue,
  elevation: 4,
  leading: IconButton(
    icon: Icon(Icons.menu),
    onPressed: () {
      // Open drawer
    },
  ),
  actions: [
    IconButton(
      icon: Icon(Icons.search),
      onPressed: () {
        // Search action
      },
    ),
    IconButton(
      icon: Icon(Icons.more_vert),
      onPressed: () {
        // More options
      },
    ),
  ],
)

AppBar widgets automatically handle back navigation and integrate with Drawer widgets for side navigation. Actions provide quick access to common functions.

Complete Flutter Widgets Example

Here’s a comprehensive example demonstrating various Flutter widgets working together in a functional application:

import 'package:flutter/material.dart';

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

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

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

class _HomeScreenState extends State<HomeScreen> {
  int _selectedIndex = 0;
  final TextEditingController _textController = TextEditingController();
  List<String> _items = ['Item 1', 'Item 2', 'Item 3'];
  
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }
  
  void _addItem() {
    if (_textController.text.isNotEmpty) {
      setState(() {
        _items.add(_textController.text);
        _textController.clear();
      });
    }
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Widgets Example'),
        backgroundColor: Colors.blue,
        actions: [
          IconButton(
            icon: Icon(Icons.info),
            onPressed: () {
              showDialog(
                context: context,
                builder: (context) => AlertDialog(
                  title: Text('Information'),
                  content: Text('This app demonstrates various Flutter widgets.'),
                  actions: [
                    TextButton(
                      onPressed: () => Navigator.pop(context),
                      child: Text('OK'),
                    ),
                  ],
                ),
              );
            },
          ),
        ],
      ),
      body: _buildBody(),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.list),
            label: 'List',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings),
            label: 'Settings',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.blue,
        onTap: _onItemTapped,
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _addItem,
        tooltip: 'Add Item',
        child: Icon(Icons.add),
      ),
    );
  }
  
  Widget _buildBody() {
    switch (_selectedIndex) {
      case 0:
        return _buildHomeTab();
      case 1:
        return _buildListTab();
      case 2:
        return _buildSettingsTab();
      default:
        return _buildHomeTab();
    }
  }
  
  Widget _buildHomeTab() {
    return SingleChildScrollView(
      padding: EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            width: double.infinity,
            height: 200,
            decoration: BoxDecoration(
              color: Colors.blue[100],
              borderRadius: BorderRadius.circular(12),
            ),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(
                  Icons.flutter_dash,
                  size: 64,
                  color: Colors.blue,
                ),
                SizedBox(height: 16),
                Text(
                  'Welcome to Flutter Widgets',
                  style: TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                    color: Colors.blue[800],
                  ),
                ),
              ],
            ),
          ),
          SizedBox(height: 24),
          Text(
            'Quick Actions',
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
            ),
          ),
          SizedBox(height: 16),
          Row(
            children: [
              Expanded(
                child: ElevatedButton.icon(
                  onPressed: () {
                    ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(content: Text('Action 1 pressed')),
                    );
                  },
                  icon: Icon(Icons.star),
                  label: Text('Action 1'),
                ),
              ),
              SizedBox(width: 16),
              Expanded(
                child: OutlinedButton.icon(
                  onPressed: () {
                    ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(content: Text('Action 2 pressed')),
                    );
                  },
                  icon: Icon(Icons.favorite),
                  label: Text('Action 2'),
                ),
              ),
            ],
          ),
          SizedBox(height: 24),
          TextField(
            controller: _textController,
            decoration: InputDecoration(
              labelText: 'Add new item',
              hintText: 'Enter item name',
              border: OutlineInputBorder(),
              prefixIcon: Icon(Icons.add),
              suffixIcon: IconButton(
                icon: Icon(Icons.clear),
                onPressed: () {
                  _textController.clear();
                },
              ),
            ),
          ),
        ],
      ),
    );
  }
  
  Widget _buildListTab() {
    return ListView.builder(
      padding: EdgeInsets.all(16),
      itemCount: _items.length,
      itemBuilder: (context, index) {
        return Card(
          margin: EdgeInsets.only(bottom: 8),
          child: ListTile(
            leading: CircleAvatar(
              backgroundColor: Colors.blue,
              child: Text('${index + 1}'),
            ),
            title: Text(_items[index]),
            subtitle: Text('Item description'),
            trailing: PopupMenuButton(
              itemBuilder: (context) => [
                PopupMenuItem(
                  child: Text('Edit'),
                  value: 'edit',
                ),
                PopupMenuItem(
                  child: Text('Delete'),
                  value: 'delete',
                ),
              ],
              onSelected: (value) {
                if (value == 'delete') {
                  setState(() {
                    _items.removeAt(index);
                  });
                }
              },
            ),
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => DetailScreen(
                    title: _items[index],
                    description: 'Detailed view of ${_items[index]}',
                  ),
                ),
              );
            },
          ),
        );
      },
    );
  }
  
  Widget _buildSettingsTab() {
    return ListView(
      padding: EdgeInsets.all(16),
      children: [
        Card(
          child: Column(
            children: [
              SwitchListTile(
                title: Text('Enable Notifications'),
                subtitle: Text('Receive app notifications'),
                value: true,
                onChanged: (value) {
                  // Handle switch change
                },
                secondary: Icon(Icons.notifications),
              ),
              Divider(),
              CheckboxListTile(
                title: Text('Dark Mode'),
                subtitle: Text('Use dark theme'),
                value: false,
                onChanged: (value) {
                  // Handle checkbox change
                },
                secondary: Icon(Icons.dark_mode),
              ),
            ],
          ),
        ),
        SizedBox(height: 16),
        Card(
          child: Column(
            children: [
              ListTile(
                leading: Icon(Icons.info),
                title: Text('About'),
                trailing: Icon(Icons.arrow_forward_ios),
                onTap: () {
                  // Navigate to about page
                },
              ),
              Divider(),
              ListTile(
                leading: Icon(Icons.help),
                title: Text('Help'),
                trailing: Icon(Icons.arrow_forward_ios),
                onTap: () {
                  // Navigate to help page
                },
              ),
            ],
          ),
        ),
      ],
    );
  }
  
  @override
  void dispose() {
    _textController.dispose();
    super.dispose();
  }
}

class DetailScreen extends StatelessWidget {
  final String title;
  final String description;
  
  const DetailScreen({
    Key? key,
    required this.title,
    required this.description,
  }) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
        backgroundColor: Colors.blue,
      ),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              title,
              style: TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
            SizedBox(height: 16),
            Text(
              description,
              style: TextStyle(fontSize: 16),
            ),
            Spacer(),
            Container(
              width: double.infinity,
              child: ElevatedButton(
                onPressed: () {
                  Navigator.pop(context);
                },
                child: Text('Go Back'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

This comprehensive Flutter widgets example demonstrates a complete application using various Flutter widget types including StatefulWidget, StatelessWidget, layout widgets, interactive widgets, and navigation widgets. The app features multiple tabs, dynamic content management, and proper state handling, showcasing how Flutter widgets work together to create engaging user interfaces.

Flutter widgets provide the foundation for building beautiful, responsive applications across multiple platforms. Understanding these Flutter widget fundamentals enables developers to create sophisticated mobile applications with rich user interactions and smooth performance. Visit the official Flutter documentation to explore more Flutter widgets and advanced techniques for your next project.