Widgets

Flutter widget reference — StatefulWidgets, StatelessWidgets, layout widgets, and common UI patterns

Everything in Flutter is a widget. Here’s a reference for the most commonly used widgets and their properties.

StatelessWidget

For widgets that don’t change over time. Their build method is called once.

class Greeting extends StatelessWidget {
  final String name;

  const Greeting({required this.name, super.key});

  @override
  Widget build(BuildContext context) {
    return Text('Hello, $name!');
  }
}

StatefulWidget

For widgets that have mutable state. When state changes, build is called again.

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: Text('Increment'),
        ),
      ],
    );
  }
}

Scaffold — page structure

Scaffold(
  appBar: AppBar(
    title: Text('My App'),
    actions: [
      IconButton(icon: Icon(Icons.settings), onPressed: () {}),
    ],
  ),
  body: Center(child: Text('Hello')),
  floatingActionButton: FloatingActionButton(
    onPressed: () {},
    child: Icon(Icons.add),
  ),
  bottomNavigationBar: NavigationBar(
    destinations: [
      NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
      NavigationDestination(icon: Icon(Icons.search), label: 'Search'),
    ],
  ),
  drawer: Drawer(child: ListView(children: [])),
)

Layout widgets

Column — vertical layout

Column(
  mainAxisAlignment: MainAxisAlignment.center,    // vertical alignment
  crossAxisAlignment: CrossAxisAlignment.start,     // horizontal alignment
  mainAxisSize: MainAxisSize.min,                  // shrink-wrap
  children: [
    Text('First'),
    Text('Second'),
    Text('Third'),
  ],
)

Row — horizontal layout

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly, // horizontal alignment
  crossAxisAlignment: CrossAxisAlignment.center,      // vertical alignment
  children: [
    Icon(Icons.star),
    Text('Label'),
    Icon(Icons.arrow_forward),
  ],
)

Stack — overlapping widgets

Stack(
  alignment: Alignment.center,
  children: [
    Image.asset('background.png'),
    Positioned(
      top: 20,
      left: 20,
      child: Text('Overlay'),
    ),
    Positioned.fill(
      child: Container(color: Colors.black.withOpacity(0.3)),
    ),
  ],
)

Container — styling wrapper

Container(
  width: 200,
  height: 100,
  padding: EdgeInsets.all(16),
  margin: EdgeInsets.symmetric(horizontal: 8),
  decoration: BoxDecoration(
    color: Colors.blue,
    borderRadius: BorderRadius.circular(12),
    boxShadow: [
      BoxShadow(
        color: Colors.black26,
        blurRadius: 4,
        offset: Offset(2, 2),
      ),
    ],
  ),
  child: Center(child: Text('Hello')),
)

ListView — scrollable list

// Fixed list
ListView(
  padding: EdgeInsets.all(8),
  children: [
    ListTile(title: Text('Item 1')),
    ListTile(title: Text('Item 2')),
  ],
)

// Dynamic list (lazy loading)
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(title: Text(items[index].name));
  },
)

// Separated list
ListView.separated(
  itemCount: items.length,
  separatorBuilder: (context, index) => Divider(),
  itemBuilder: (context, index) {
    return ListTile(title: Text(items[index].name));
  },
)

GridView — grid layout

GridView.builder(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 2,           // 2 columns
    mainAxisSpacing: 8,
    crossAxisSpacing: 8,
    childAspectRatio: 1.0,       // width / height ratio
  ),
  itemCount: items.length,
  itemBuilder: (context, index) {
    return Card(child: Center(child: Text(items[index].name)));
  },
)

Input widgets

// Text field
TextField(
  decoration: InputDecoration(
    labelText: 'Email',
    hintText: 'Enter your email',
    prefixIcon: Icon(Icons.email),
    border: OutlineInputBorder(),
  ),
  onChanged: (value) => print(value),
  keyboardType: TextInputType.emailAddress,
);

// Elevated button
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('Submit'),
);

// Text button (no background)
TextButton(onPressed: () {}, child: Text('Learn More'));

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

// Switch
Switch(value: isEnabled, onChanged: (val) => setState(() => isEnabled = val));

// Checkbox
Checkbox(value: isChecked, onChanged: (val) => setState(() => isChecked = val!));

// Slider
Slider(value: volume, min: 0, max: 100, onChanged: (val) => setState(() => volume = val));

Dialog widgets

// AlertDialog
showDialog(
  context: context,
  builder: (context) => AlertDialog(
    title: Text('Confirm'),
    content: Text('Are you sure?'),
    actions: [
      TextButton(onPressed: () => Navigator.pop(context), child: Text('Cancel')),
      ElevatedButton(onPressed: () => Navigator.pop(context, true), child: Text('OK')),
    ],
  ),
);

// BottomSheet
showModalBottomSheet(
  context: context,
  builder: (context) => Padding(
    padding: EdgeInsets.all(16),
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Text('Options'),
        ListTile(title: Text('Option 1'), onTap: () => Navigator.pop(context)),
      ],
    ),
  ),
);

// Snackbar
ScaffoldMessenger.of(context).showSnackBar(
  SnackBar(content: Text('Item saved'), action: SnackBarAction(label: 'Undo', onPressed: () {})),
);