Everything in Flutter is a widget. Text, buttons, images, layouts — all widgets. Your app is a tree of widgets nested inside each other.
StatelessWidget vs StatefulWidget
Dart
// Stateless — no mutable state, just displays data
class Greeting extends StatelessWidget {
final String name;
const Greeting({super.key, required this.name});
@override
Widget build(BuildContext context) {
return Text('Hello, $name!');
}
}
// Stateful — can change over time
class Counter extends StatefulWidget {
const Counter({super.key});
@override
State<Counter> createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int count = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Count: $count'),
ElevatedButton(
onPressed: () => setState(() => count++),
child: const Text('Increment'),
),
],
);
}
}Common Widgets
Dart
// Text with styling
Text('Hello', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold))
// Buttons
ElevatedButton(onPressed: () {}, child: Text('Click me'))
TextButton(onPressed: () {}, child: Text('Text button'))
IconButton(onPressed: () {}, icon: Icon(Icons.star))
// Images
Image.network('https://example.com/photo.jpg')
Image.asset('assets/logo.png')
// Container (box with padding, margin, decoration)
Container(
padding: EdgeInsets.all(16),
margin: EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
color: Colors.blue[50],
borderRadius: BorderRadius.circular(12),
),
child: Text('Styled box'),
)Layout Widgets
Dart
// Row — horizontal
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [Text('A'), Text('B'), Text('C')],
)
// Column — vertical
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text('First'), Text('Second'), Text('Third')],
)
// Stack — overlapping
Stack(
children: [
Image.network('photo.jpg'),
Positioned(
bottom: 8, left: 8,
child: Text('Label', style: TextStyle(color: Colors.white)),
),
],
)
// Expanded — fills remaining space
Row(
children: [
Expanded(flex: 2, child: Container(color: Colors.red)),
Expanded(flex: 1, child: Container(color: Colors.blue)),
],
)Padding and Spacing
Dart
Padding(
padding: EdgeInsets.all(16),
child: Text('Padded content'),
)
SizedBox(height: 20) // invisible spacer
Divider() // horizontal lineTips
- Use
constconstructors when possible — Flutter skips rebuilding const widgets. - Prefer
StatelessWidgetunless you need mutable state. - Use
ExpandedandFlexibleinsideRow/Columnto control layout. - Keep widget trees shallow — extract into separate widgets when nesting deepens.
Next: state.