Widget Cheat Sheet
App Structure
MaterialApp
The root widget for a Material Design app. Configures theme, routes, and home screen.
MaterialApp(
title: 'My App',
theme: ThemeData(primarySwatch: Colors.blue),
home: HomeScreen(),
)
Scaffold
Provides the basic page structure: app bar, body, floating action button, bottom navigation, and drawers.
Scaffold(
appBar: AppBar(title: Text('Title')),
body: Center(child: Text('Hello')),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
),
)
Layout Widgets
Row & Column
Lay out children horizontally (Row) or vertically (Column).
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Left'),
Text('Right'),
],
)
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Top'),
Text('Bottom'),
],
)
Key properties:
- mainAxisAlignment — How children are distributed along the main axis
- crossAxisAlignment — How children are aligned along the cross axis
- mainAxisSize — Whether the axis takes minimum or maximum space
Container
A convenience widget combining decoration, padding, margin, and sizing.
Container(
width: 200,
height: 100,
padding: EdgeInsets.all(16),
margin: EdgeInsets.symmetric(vertical: 8),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
boxShadow: [BoxShadow(blurRadius: 4, color: Colors.black26)],
),
child: Text('Styled box'),
)
Expanded & Flexible
Control how children share space inside a Row or Column.
Row(
children: [
Expanded(flex: 2, child: Container(color: Colors.red)),
Expanded(flex: 1, child: Container(color: Colors.blue)),
],
)
Stack & Positioned
Layer widgets on top of each other.
Stack(
children: [
Image.asset('background.png'),
Positioned(
bottom: 16,
right: 16,
child: Text('Overlay'),
),
],
)
SizedBox
Force a specific size or add whitespace.
SizedBox(height: 16) // vertical spacing
SizedBox(width: 200, child: button) // fixed-width child
SizedBox.expand() // fill all available space
Padding
Add space around a child.
Padding(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Text('Padded text'),
)
Wrap
Like Row, but wraps to the next line when it runs out of space.
Wrap(
spacing: 8,
runSpacing: 4,
children: chips,
)
Scrolling Widgets
ListView
A scrollable list. Use .builder for large or dynamic lists.
// Simple (few items)
ListView(
children: [ListTile(title: Text('Item 1'))],
)
// Builder (many items — only builds visible ones)
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) => ListTile(
title: Text(items[index]),
),
)
// Separated (with dividers)
ListView.separated(
itemCount: items.length,
itemBuilder: (context, index) => ListTile(title: Text(items[index])),
separatorBuilder: (context, index) => Divider(),
)
GridView
A scrollable 2D grid.
GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
children: cards,
)
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
itemCount: items.length,
itemBuilder: (context, index) => Card(child: Text('$index')),
)
SingleChildScrollView
Makes a single child scrollable. Good for forms and content that might overflow.
SingleChildScrollView(
child: Column(children: manyWidgets),
)
Text & Styling
Text
Display styled text.
Text(
'Hello, Flutter!',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blue,
letterSpacing: 1.2,
),
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis,
)
RichText
Mix multiple styles in a single text block.
RichText(
text: TextSpan(
text: 'Hello ',
style: DefaultTextStyle.of(context).style,
children: [
TextSpan(text: 'bold', style: TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: ' world'),
],
),
)
Buttons
Common Button Types
ElevatedButton(onPressed: () {}, child: Text('Elevated'))
TextButton(onPressed: () {}, child: Text('Text'))
OutlinedButton(onPressed: () {}, child: Text('Outlined'))
IconButton(onPressed: () {}, icon: Icon(Icons.star))
FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
)
Styled Buttons
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
child: Text('Custom'),
)
Images
Displaying Images
// From assets (add to pubspec.yaml first)
Image.asset('assets/photo.png', width: 200, fit: BoxFit.cover)
// From network
Image.network('https://example.com/photo.png')
// With placeholder and error handling
FadeInImage.assetNetwork(
placeholder: 'assets/loading.gif',
image: 'https://example.com/photo.png',
)
// Circular avatar
CircleAvatar(
radius: 40,
backgroundImage: AssetImage('assets/avatar.png'),
)
Input & Forms
TextField
TextField(
controller: _controller,
decoration: InputDecoration(
labelText: 'Email',
hintText: 'you@example.com',
prefixIcon: Icon(Icons.email),
border: OutlineInputBorder(),
),
keyboardType: TextInputType.emailAddress,
onChanged: (value) => print(value),
)
Form with Validation
final _formKey = GlobalKey<FormState>();
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) return 'Required';
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
// Process data
}
},
child: Text('Submit'),
),
],
),
)
Other Input Widgets
Switch(value: isOn, onChanged: (val) => setState(() => isOn = val))
Checkbox(value: isChecked, onChanged: (val) => setState(() => isChecked = val!))
Slider(value: volume, min: 0, max: 100, onChanged: (val) => setState(() => volume = val))
DropdownButton<String>(
value: selected,
items: options.map((o) => DropdownMenuItem(value: o, child: Text(o))).toList(),
onChanged: (val) => setState(() => selected = val!),
)
Navigation
Push & Pop
// Push a new screen
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailScreen()),
);
// Pop back
Navigator.pop(context);
// Push and pass data back
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => SelectionScreen()),
);
Named Routes
// In MaterialApp
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => HomeScreen(),
'/detail': (context) => DetailScreen(),
},
)
// Navigate
Navigator.pushNamed(context, '/detail');
State Management Patterns
setState (simplest)
class CounterWidget extends StatefulWidget {
@override
State<CounterWidget> createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int _count = 0;
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => setState(() => _count++),
child: Text('Count: $_count'),
);
}
}
Provider (recommended for most apps)
// Define
class Counter extends ChangeNotifier {
int value = 0;
void increment() { value++; notifyListeners(); }
}
// Provide
ChangeNotifierProvider(create: (_) => Counter(), child: MyApp())
// Consume
final counter = context.watch<Counter>();
Text('${counter.value}')
Async Widgets
FutureBuilder
Build a widget based on the result of a Future.
FutureBuilder<String>(
future: fetchData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
if (snapshot.hasError) return Text('Error: ${snapshot.error}');
return Text(snapshot.data!);
},
)
StreamBuilder
Build a widget that updates as a Stream emits values.
StreamBuilder<int>(
stream: counterStream,
builder: (context, snapshot) {
return Text('Count: ${snapshot.data ?? 0}');
},
)
Theming
ThemeData
MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
textTheme: TextTheme(
headlineLarge: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
bodyMedium: TextStyle(fontSize: 16),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
),
),
)
Using Theme Values
final colorScheme = Theme.of(context).colorScheme;
final textTheme = Theme.of(context).textTheme;
Text('Styled', style: textTheme.headlineLarge)
Container(color: colorScheme.primary)
Common Patterns
Show a Dialog
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Confirm'),
content: Text('Are you sure?'),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: Text('Cancel')),
TextButton(onPressed: () { /* do it */ Navigator.pop(context); }, child: Text('OK')),
],
),
);
Show a SnackBar
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Item deleted'),
action: SnackBarAction(label: 'Undo', onPressed: () {}),
),
);
GestureDetector
Detect taps, swipes, and other gestures on any widget.
GestureDetector(
onTap: () => print('tapped'),
onLongPress: () => print('long press'),
child: Container(color: Colors.blue, width: 100, height: 100),
)