Checkbox, RadioButton

Checkbox flips an independent bool; Radio wins exclusivity through a SHARED groupValue variable, not a shared container: Flutter moved the radio group from layout into state.

11 min read · 9 cards · 2 checks

Read in: English · हिन्दी · ગુજરાતી


Theory

The form asks two kinds of question

FestConnect Flutter's registration form has reached its choices section:

Add a carry bag? Get event updates?: independent yes/nos: tick any, tick both.

Payment: Cash, Card or UPI?: exactly one.

You have met this split twice: BCA404's CheckBox-vs-RadioButton and Unit 1's Android widgets. Flutter keeps the split, keeps the controlled-widget law from last lesson: and quietly relocates where radio EXCLUSIVITY comes from, in a way that catches every Android and VB veteran.

Theory

Checkbox: one bool each, forever independent

Each checkbox is a controlled widget wrapped around its own bool:

bool carryBag = false;

Checkbox(

value: carryBag,

onChanged: (v) => setState(() { carryBag = v!; }),

)

The slider's loop verbatim: value displays the state, onChanged publishes the flip. Two checkboxes = 2 bools = total independence: which is precisely the any-of semantics. The labelled convenience form is CheckboxListTile (checkbox + title in one tappable row).

Practical

Both question kinds, one form

class _RegisterState extends State<RegisterScreen> {
  bool carryBag = false;        // checkbox: own bool each
  bool wantsUpdates = true;
  String payMode = 'upi';       // ONE variable = ONE radio group

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        CheckboxListTile(
          title: const Text('Add a carry bag (Rs 10)'),
          value: carryBag,
          onChanged: (v) => setState(() { carryBag = v!; }),
        ),
        CheckboxListTile(
          title: const Text('Send me event updates'),
          value: wantsUpdates,
          onChanged: (v) => setState(() { wantsUpdates = v!; }),
        ),
        RadioListTile<String>(
          title: const Text('Cash'),
          value: 'cash',                 // this radio's identity
          groupValue: payMode,           // the SHARED group variable
          onChanged: (v) => setState(() { payMode = v!; }),
        ),
        RadioListTile<String>(
          title: const Text('Card'),
          value: 'card',
          groupValue: payMode,
          onChanged: (v) => setState(() { payMode = v!; }),
        ),
        RadioListTile<String>(
          title: const Text('UPI'),
          value: 'upi',                  // equals payMode: renders selected
          groupValue: payMode,
          onChanged: (v) => setState(() { payMode = v!; }),
        ),
      ],
    );
  }
}

Theory

Radio: exclusivity by shared variable

Read the radio trio's machinery:

  • each Radio carries a value: its identity ('cash', 'card', 'upi')
  • all 3 point their groupValue at the SAME state variable, payMode
  • the radio whose value == groupValue renders selected: with payMode = 'upi', the UPI row shows the dot
  • tapping Card runs setState(payMode = 'card'): ONE assignment, and the rebuild repaints ALL 3 radios against the new groupValue: Card gains the dot, UPI loses it

No RadioGroup, no GroupBox, no container anywhere: the group IS the shared variable.

Quiz

In Flutter, what makes 3 Radio widgets behave as one exclusive group?

  1. Placing them inside the same Column or container
  2. All 3 sharing the same groupValue state variable
  3. Giving them the same value parameter
  4. Wrapping them in a RadioGroup widget, like Android
Show the answer

All 3 sharing the same groupValue state variable

The group lives in STATE, not layout: 3 radios reading one payMode variable are one group wherever they sit on screen: even scattered across different Rows. Option A is the reflex this question hunts: BCA404's GroupBox and Android's RadioGroup defined groups by CONTAINER, and Flutter deliberately does not. Option C would give 3 radios the same IDENTITY: they would all select together, the opposite of exclusive. Option D imports a widget Flutter does not ship. Exam sentence: exclusivity follows the shared groupValue; selection is value == groupValue.

Think first

Two questions, so how many variables?

The form grows a second radio question: Delivery: Take away / Home delivery. In BCA404 this needed a second GroupBox. What does it need in Flutter, and what goes wrong if you lazily reuse payMode for both questions? Trace it, then tap.

Show the answer

A second state variable: String delivery = 'takeaway'; and the 2 new radios point groupValue at THAT. Reuse payMode for both and all 5 radios form ONE accidental group: choosing Home delivery (payMode = 'home') deselects UPI, and your payment silently becomes 'home': the same merged-group bug as BCA404's radios on a bare form, relocated from layout into state. The mapping to write in your notes: one QUESTION = one groupValue variable, exactly as one question = one container in the old worlds.

Watch out

Choice-widget slips

onChanged: null freezes them: like buttons, a null handler renders the control disabled: useful deliberately, baffling accidentally.

The v! bang: onChanged hands a nullable (bool? / T?); v! asserts non-null before storing: modern Dart's null safety showing its teeth.

Checkbox for one-of questions: 2 payment checkboxes both ticked is a data bug born in the form design: the BCA404 rule (any-of = check, one-of = radio) survives all 3 platforms.

Theory

The controlled-widget law, second and third witnesses

Checkbox and Radio just re-testified: value from state, change through onChanged + setState: and Radio added the insight that even GROUPING is state in Flutter. This is the philosophical heart of the framework: layout arranges, state decides, widgets merely display. Unit 5 opens next with the progress indicators and a deeper Stack: the loading overlay every real booking flow needs.

Summary

Key takeaways

  • Checkbox: value (its own bool) + onChanged + setState: independent any-of choices; CheckboxListTile for labelled rows.
  • Radio<T>: value is the radio's identity; groupValue points at the shared state variable; selected when value == groupValue.
  • Exclusivity comes from the SHARED groupValue: not from containers (the Android/VB.NET contrast).
  • One question = one groupValue variable; reusing one across questions merges the groups.
  • onChanged: null disables; handlers receive nullables (hence v!).
  • Any-of = checkbox, one-of = radio: the rule survives its third platform.
  • Memory hook: the group is a variable, not a box.

Study this properly

This page is the lesson to read. In Gri-Learn the same topic is a graded deck: the self-checks are scored and your weak topics are tracked. Free to start.

Start this topic

Already have an account? Sign in

More from Flutter basic widgets

Gri-Learn · syllabus-mapped B.C.A. lessons in English, Hindi and Gujarati

Checkbox, RadioButton · Mobile Application Development - 2 (option B) · Gri-Learn