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