flutter
/

Flutter Checkbox – Complete Guide with CheckboxListTile

Last Sync: Today

On this page

9
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

flutter

Flutter Checkbox – Complete Guide with CheckboxListTile

What is a Checkbox in Flutter?

A checkbox is a UI element that allows the user to toggle a binary state (checked/unchecked). In Flutter, the Checkbox widget provides a simple square box, while CheckboxListTile combines it with a label, making it easier to use in forms and lists. Checkboxes are ideal for accepting terms, selecting multiple options, or any yes/no choice.

Basic Checkbox Widget

The Checkbox widget requires two main parameters: value (bool) and onChanged (callback). When the user taps, onChanged is called with the new value (the opposite of the current value).

DARTRead-only
1
bool _isChecked = false;

Checkbox(
  value: _isChecked,
  onChanged: (bool? newValue) {
    setState(() {
      _isChecked = newValue ?? false;
    });
  },
)

Note that onChanged receives a nullable bool. Always provide a fallback (e.g., ?? false).

Using CheckboxListTile for Better UI

CheckboxListTile wraps a checkbox with a title, subtitle, and optional leading/trailing widgets. It handles the layout and provides a larger tap target. It's perfect for lists and forms.

DARTRead-only
1
CheckboxListTile(
  value: _isChecked,
  title: Text('Accept terms and conditions'),
  subtitle: Text('You must agree to continue'),
  onChanged: (bool? newValue) {
    setState(() => _isChecked = newValue ?? false);
  },
)

Customizing Checkbox Appearance

You can customize the checkbox's colors, size, and shape:

    • activeColor: Color when checked.
    • checkColor: Color of the check mark.
    • fillColor: Overrides the fill color (MaterialStateProperty).
    • visualDensity: Adjusts compactness.
    • shape: Defines the shape of the checkbox (e.g., RoundedRectangleBorder).
DARTRead-only
1
Checkbox(
  value: _isChecked,
  activeColor: Colors.green,
  checkColor: Colors.white,
  visualDensity: VisualDensity.compact,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(4),
  ),
  onChanged: (value) => setState(() => _isChecked = value ?? false),
)

Working with Multiple Checkboxes

When you have multiple checkboxes (e.g., a list of options), you typically store each checkbox's state in a list or map. Use CheckboxListTile inside a ListView or Column.

DARTRead-only
1
List<String> _options = ['Apple', 'Banana', 'Orange'];
List<bool> _checked = [false, false, false];

...

ListView.builder(
  itemCount: _options.length,
  itemBuilder: (context, index) {
    return CheckboxListTile(
      value: _checked[index],
      title: Text(_options[index]),
      onChanged: (bool? newValue) {
        setState(() {
          _checked[index] = newValue ?? false;
        });
      },
    );
  },
)

Checkbox in Forms

To use a checkbox in a Form, you can create a custom FormField or simply manage the checkbox state in the widget and read its value during form submission. For validation, you can check the checkbox's value and show an error message manually.

DARTRead-only
1
class _FormState extends State<MyForm> {
  final _formKey = GlobalKey<FormState>();
  bool _accepted = false;
  String? _acceptError;

  void _submit() {
    setState(() {
      if (!_accepted) {
        _acceptError = 'You must accept the terms';
      } else {
        _acceptError = null;
        // proceed
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          CheckboxListTile(
            value: _accepted,
            title: Text('I accept the terms'),
            onChanged: (value) {
              setState(() => _accepted = value ?? false);
              if (value == true) _acceptError = null;
            },
          ),
          if (_acceptError != null)
            Text(_acceptError!, style: TextStyle(color: Colors.red)),
          ElevatedButton(
            onPressed: _submit,
            child: Text('Submit'),
          ),
        ],
      ),
    );
  }
}

Common Mistakes

    • Forgetting to call setState – The checkbox won't visually update.
    • Not handling null in onChanged – If you don't handle nullable, you might get a type error.
    • Using Checkbox without a label – Users may not understand its purpose; always include a label or tooltip.
    • Not providing a default value – If value is null, the checkbox appears indeterminate (dash).
    • Over‑customizing – Changing the shape too drastically may confuse users.

Best Practices

    • Use CheckboxListTile when you need a label; it provides better UX.
    • For multiple checkboxes, store state in a list of booleans or a map.
    • In forms, validate checkboxes and show clear error messages.
    • Consider using ToggleButtons for a set of mutually exclusive options if appropriate.

Key Takeaways

    • Checkbox is the basic toggle widget; CheckboxListTile adds a label and larger tap area.
    • Use value and onChanged to control the state.
    • Customize colors, shapes, and density for styling.
    • For multiple checkboxes, store states in a list.
    • For forms, validate manually or create a custom FormField.

Try it yourself

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Checkbox Demo',
      home: Scaffold(
        appBar: AppBar(title: Text('Checkbox Example')),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Center(child: CheckboxDemo()),
        ),
      ),
    );
  }
}

class CheckboxDemo extends StatefulWidget {
  @override
  _CheckboxDemoState createState() => _CheckboxDemoState();
}

class _CheckboxDemoState extends State<CheckboxDemo> {
  bool _isChecked = false;
  List<bool> _optionsChecked = [false, false, false];
  final List<String> _options = ['Option A', 'Option B', 'Option C'];

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        CheckboxListTile(
          value: _isChecked,
          title: Text('Accept terms'),
          onChanged: (value) => setState(() => _isChecked = value ?? false),
        ),
        SizedBox(height: 20),
        Text('Select options:'),
        ...List.generate(_options.length, (index) {
          return CheckboxListTile(
            value: _optionsChecked[index],
            title: Text(_options[index]),
            onChanged: (value) {
              setState(() => _optionsChecked[index] = value ?? false);
            },
          );
        }),
        SizedBox(height: 20),
        Text('Accepted: ${_isChecked ? 'Yes' : 'No'}'),
        Text('Selected options: ${_options.where((_, i) => _optionsChecked[i]).join(', ')}'),
      ],
    );
  }
}

Test Your Knowledge

Q1
of 4

What type does the `value` property of a Checkbox accept?

A
bool
B
bool?
C
int
D
String
Q2
of 4

Which widget combines a checkbox with a title and larger tap area?

A
Checkbox
B
CheckboxTile
C
CheckboxListTile
D
ListTileCheckbox
Q3
of 4

How do you disable a checkbox?

A
Set `enabled: false`
B
Set `onChanged: null`
C
Set `disabled: true`
D
Set `active: false`
Q4
of 4

What happens if you set `value` to `null` on a Checkbox?

A
The checkbox is unchecked
B
The checkbox shows a dash (indeterminate)
C
An error occurs
D
The checkbox is hidden

Frequently Asked Questions

How do I set a checkbox to be checked by default?

Initialize the value variable to true. For example: bool _isChecked = true;

Can I make a checkbox read‑only?

Yes, set onChanged: null. The checkbox will be disabled (greyed out) and cannot be toggled.

How do I create a tri‑state checkbox?

Flutter's checkbox can be in three states: true (checked), false (unchecked), and null (indeterminate). To use the indeterminate state, set value: null and provide a custom visual if needed. However, most apps use only true/false.

What is the difference between `Checkbox` and `CheckboxListTile`?

Checkbox is just the square box. CheckboxListTile combines the checkbox with a title, subtitle, and optional leading/trailing widgets, making it easier to align and providing a larger touch area.

Previous

flutter form validation

Next

flutter radio button

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.