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!),
)

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'),
    );
  }
}
// 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),
)
1 / 1