Question #221EasyFlutter Basics

Different types of widgets in flutter ?

#flutter#widget

Answer

Different Types of Widgets in Flutter

Flutter widgets are the building blocks of the UI. Understanding widget types is crucial for building efficient and maintainable Flutter applications.

Widget Categories

CategoryPurposeExamples
StatelessImmutable UIText, Icon, Container
StatefulMutable stateCheckbox, TextField, AnimatedWidget
InheritedData propagationTheme, MediaQuery
LayoutArrangementRow, Column, Stack
UIVisual elementsButton, Card, AppBar
PlatformOS-specificCupertino, Material

1. Stateless Widgets

Widgets that don't have mutable state. They are rebuilt only when their parent changes.

dart
class StatelessExample extends StatelessWidget {
  final String title;
  final String subtitle;

  const StatelessExample({
    Key? key,
    required this.title,
    required this.subtitle,
  }) : super(key: key);

  
  Widget build(BuildContext context) {
    return Card(
      child: Column(
        children: [
          Text(title),
          Text(subtitle),
        ],
      ),
    );
  }
}

// Common stateless widgets
Text('Hello')
Icon(Icons.home)
Container(color: Colors.blue)
Center(child: Text('Centered'))
Padding(padding: EdgeInsets.all(8))

2. Stateful Widgets

Widgets that maintain mutable state across rebuilds.

dart
class StatefulExample extends StatefulWidget {
  
  _StatefulExampleState createState() => _StatefulExampleState();
}

class _StatefulExampleState extends State<StatefulExample> {
  int _counter = 0;
  bool _isChecked = false;
  String _text = '';

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Counter: $_counter'),
        ElevatedButton(
          onPressed: () => setState(() => _counter++),
          child: Text('Increment'),
        ),
        Checkbox(
          value: _isChecked,
          onChanged: (value) => setState(() => _isChecked = value!),
        ),
        TextField(
          onChanged: (value) => setState(() => _text = value),
        ),
      ],
    );
  }
}

// Common stateful widgets
TextField()
Checkbox(value: true, onChanged: (v) {})
Switch(value: true, onChanged: (v) {})
Slider(value: 0.5, onChanged: (v) {})
AnimatedContainer(duration: Duration(seconds: 1))

3. Inherited Widgets

Special widgets that efficiently propagate data down the widget tree.

dart
class UserInherited extends InheritedWidget {
  final String username;
  final String email;

  const UserInherited({
    required this.username,
    required this.email,
    required Widget child,
  }) : super(child: child);

  static UserInherited? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<UserInherited>();
  }

  
  bool updateShouldNotify(UserInherited oldWidget) {
    return oldWidget.username != username || oldWidget.email != email;
  }
}

// Usage
class ProfileWidget extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final user = UserInherited.of(context);
    return Text('User: ${user?.username}');
  }
}

// Common inherited widgets
Theme.of(context)
MediaQuery.of(context)
Navigator.of(context)
ScaffoldMessenger.of(context)

4. Layout Widgets

Widgets that arrange child widgets in specific patterns.

dart
// Row - Horizontal arrangement
Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    Text('Left'),
    Text('Center'),
    Text('Right'),
  ],
)

// Column - Vertical arrangement
Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Text('Top'),
    Text('Middle'),
    Text('Bottom'),
  ],
)

// Stack - Overlapping widgets
Stack(
  alignment: Alignment.center,
  children: [
    Container(width: 200, height: 200, color: Colors.blue),
    Text('Overlaid Text'),
  ],
)

// Flex - Flexible layout
Flex(
  direction: Axis.horizontal,
  children: [
    Expanded(child: Container(color: Colors.red)),
    Expanded(flex: 2, child: Container(color: Colors.blue)),
  ],
)

// Wrap - Flowing layout
Wrap(
  spacing: 8,
  runSpacing: 8,
  children: [
    Chip(label: Text('Tag 1')),
    Chip(label: Text('Tag 2')),
    Chip(label: Text('Tag 3')),
  ],
)

// GridView - Grid layout
GridView.count(
  crossAxisCount: 3,
  children: List.generate(9, (index) =>
    Card(child: Center(child: Text('$index')))),
)

5. UI Widgets

Visual elements that users interact with or see.

dart
// Buttons
ElevatedButton(
  onPressed: () {},
  child: Text('Elevated'),
)

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

OutlinedButton(
  onPressed: () {},
  child: Text('Outlined'),
)

IconButton(
  icon: Icon(Icons.favorite),
  onPressed: () {},
)

FloatingActionButton(
  onPressed: () {},
  child: Icon(Icons.add),
)

// Cards and Containers
Card(
  elevation: 4,
  child: Padding(
    padding: EdgeInsets.all(16),
    child: Text('Card content'),
  ),
)

Container(
  width: 100,
  height: 100,
  decoration: BoxDecoration(
    color: Colors.blue,
    borderRadius: BorderRadius.circular(8),
    boxShadow: [
      BoxShadow(
        color: Colors.black26,
        blurRadius: 4,
        offset: Offset(2, 2),
      ),
    ],
  ),
  child: Center(child: Text('Container')),
)

// AppBar and Scaffold
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('Body')),
  bottomNavigationBar: BottomNavigationBar(
    items: [
      BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
      BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
    ],
  ),
  floatingActionButton: FloatingActionButton(
    onPressed: () {},
    child: Icon(Icons.add),
  ),
)

// Dialogs and Sheets
AlertDialog(
  title: Text('Alert'),
  content: Text('This is an alert dialog'),
  actions: [
    TextButton(onPressed: () {}, child: Text('Cancel')),
    TextButton(onPressed: () {}, child: Text('OK')),
  ],
)

BottomSheet(
  onClosing: () {},
  builder: (context) => Container(
    height: 200,
    child: Center(child: Text('Bottom Sheet')),
  ),
)

6. Input Widgets

Widgets for user input.

dart
// Text input
TextField(
  decoration: InputDecoration(
    labelText: 'Enter text',
    hintText: 'Type here',
    border: OutlineInputBorder(),
  ),
  onChanged: (value) => print(value),
)

// Forms
Form(
  child: Column(
    children: [
      TextFormField(
        validator: (value) => value?.isEmpty ?? true ? 'Required' : null,
      ),
      ElevatedButton(
        onPressed: () {},
        child: Text('Submit'),
      ),
    ],
  ),
)

// Selection
Checkbox(
  value: true,
  onChanged: (value) {},
)

Radio<int>(
  value: 1,
  groupValue: 1,
  onChanged: (value) {},
)

Switch(
  value: true,
  onChanged: (value) {},
)

Slider(
  value: 0.5,
  min: 0,
  max: 1,
  onChanged: (value) {},
)

DropdownButton<String>(
  value: 'One',
  items: ['One', 'Two', 'Three'].map((String value) {
    return DropdownMenuItem<String>(
      value: value,
      child: Text(value),
    );
  }).toList(),
  onChanged: (value) {},
)

7. Scrollable Widgets

Widgets that enable scrolling content.

dart
// ListView
ListView(
  children: [
    ListTile(title: Text('Item 1')),
    ListTile(title: Text('Item 2')),
    ListTile(title: Text('Item 3')),
  ],
)

ListView.builder(
  itemCount: 100,
  itemBuilder: (context, index) => ListTile(
    title: Text('Item $index'),
  ),
)

// GridView
GridView.count(
  crossAxisCount: 2,
  children: List.generate(20, (index) =>
    Card(child: Center(child: Text('$index')))),
)

// SingleChildScrollView
SingleChildScrollView(
  child: Column(
    children: List.generate(50, (index) =>
      Container(height: 50, child: Text('Item $index'))),
  ),
)

// CustomScrollView with Slivers
CustomScrollView(
  slivers: [
    SliverAppBar(
      title: Text('Sliver AppBar'),
      floating: true,
    ),
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (context, index) => ListTile(title: Text('Item $index')),
        childCount: 50,
      ),
    ),
  ],
)

8. Platform-Specific Widgets

Widgets that follow platform design guidelines.

dart
// Material (Android)
import 'package:flutter/material.dart';

MaterialApp(
  theme: ThemeData.light(),
  home: Scaffold(
    appBar: AppBar(title: Text('Material')),
    body: ElevatedButton(
      onPressed: () {},
      child: Text('Material Button'),
    ),
  ),
)

// Cupertino (iOS)
import 'package:flutter/cupertino.dart';

CupertinoApp(
  theme: CupertinoThemeData(),
  home: CupertinoPageScaffold(
    navigationBar: CupertinoNavigationBar(
      middle: Text('Cupertino'),
    ),
    child: CupertinoButton(
      onPressed: () {},
      child: Text('Cupertino Button'),
    ),
  ),
)

// Platform-adaptive
Widget buildButton() {
  if (Platform.isIOS) {
    return CupertinoButton(
      onPressed: () {},
      child: Text('Button'),
    );
  } else {
    return ElevatedButton(
      onPressed: () {},
      child: Text('Button'),
    );
  }
}

9. Animation Widgets

Widgets for creating animations.

dart
// Implicit animations (built-in)
AnimatedContainer(
  duration: Duration(seconds: 1),
  width: _isExpanded ? 200 : 100,
  height: _isExpanded ? 200 : 100,
  color: _isExpanded ? Colors.blue : Colors.red,
)

AnimatedOpacity(
  duration: Duration(seconds: 1),
  opacity: _isVisible ? 1.0 : 0.0,
  child: Container(color: Colors.blue),
)

// Explicit animations (custom)
class RotationAnimation extends StatefulWidget {
  
  _RotationAnimationState createState() => _RotationAnimationState();
}

class _RotationAnimationState extends State<RotationAnimation>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 2),
      vsync: this,
    )..repeat();

    _animation = Tween<double>(begin: 0, end: 2 * 3.14159).animate(_controller);
  }

  
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animation,
      builder: (context, child) {
        return Transform.rotate(
          angle: _animation.value,
          child: Container(
            width: 100,
            height: 100,
            color: Colors.blue,
          ),
        );
      },
    );
  }
}

// Hero animations
Hero(
  tag: 'hero-image',
  child: Image.network('https://example.com/image.jpg'),
)

10. Utility Widgets

Widgets that provide functionality without visual output.

dart
// SafeArea - Avoids system UI
SafeArea(
  child: Text('Safe content'),
)

// Visibility - Conditional rendering
Visibility(
  visible: _isVisible,
  child: Text('Conditionally shown'),
)

// Expanded - Fills available space
Row(
  children: [
    Expanded(child: Container(color: Colors.red)),
    Container(width: 100, color: Colors.blue),
  ],
)

// Flexible - Flexible sizing
Row(
  children: [
    Flexible(
      flex: 2,
      child: Container(color: Colors.red),
    ),
    Flexible(
      flex: 1,
      child: Container(color: Colors.blue),
    ),
  ],
)

// SizedBox - Fixed size spacing
Column(
  children: [
    Text('Top'),
    SizedBox(height: 20), // Spacing
    Text('Bottom'),
  ],
)

// Spacer - Flexible spacing
Row(
  children: [
    Text('Left'),
    Spacer(), // Takes all available space
    Text('Right'),
  ],
)

Widget Selection Guide

NeedWidget TypeExamples
No stateStatelessText, Icon, Image
Mutable stateStatefulTextField, Checkbox
Share dataInheritedTheme, MediaQuery
LayoutLayoutRow, Column, Stack
User inputInputTextField, Slider
ScrollingScrollableListView, GridView
AnimationAnimationAnimatedContainer
Platform lookPlatformMaterial, Cupertino

Important: Choose the simplest widget type that meets your requirements. Prefer stateless widgets when possible for better performance. Use stateful widgets only when you need to manage mutable state.

Learn more at Flutter Widget Catalog