Theory
Exactly one year
A FestConnect student is in exactly one year: First, Second, or Third, never two. CheckBoxes would wrongly let them tick several. You need a control where selecting one option clears the rest.
That is the RadioButton, but with a twist: a lone RadioButton does not enforce single choice. The magic comes from wrapping them in a RadioGroup. The group is what makes the buttons mutually exclusive, and that is the most-tested fact here.
Theory
Old car radio buttons
The widget is named after old car radios: a row of physical buttons where pressing one popped the others out, so only one station was ever selected. The row (the RadioGroup) is what made them exclusive; a single button alone could not do that. Android RadioButtons work the same: put them in a RadioGroup and picking one releases the others.
Theory
Group makes it single-choice
- Wrap
RadioButtons in a `RadioGroup`; that enforces 'only one selected'. - Find the selection:
group.getCheckedRadioButtonId()returns the selected button's id, or -1 if none. - Then
findViewById(thatId)gets the button; read its text orisChecked(). - React:
group.setOnCheckedChangeListener((grp, checkedId) -> { ... }).
RadioButtons can also be created dynamically in Java and added to the group; custom ones restyle the indicator.
Practical
FestConnect: pick your year
// XML: <RadioGroup id=yearGroup> with 3 RadioButtons
// First (id=y1), Second (id=y2), Third (id=y3)
RadioGroup yearGroup = findViewById(R.id.yearGroup);
register.setOnClickListener(v -> {
int id = yearGroup.getCheckedRadioButtonId();
if (id == -1) {
Toast.makeText(this, "Please pick a year", Toast.LENGTH_SHORT).show();
return;
}
RadioButton chosen = findViewById(id);
Toast.makeText(this, "Year: " + chosen.getText(), Toast.LENGTH_SHORT).show();
});
// picking 'Second' automatically un-picks 'First' (the group enforces it)Think first
What does -1 mean?
getCheckedRadioButtonId() returns -1 in one situation. When, and why is checking for it important before you call findViewById on the result?
Show the answer
It returns -1 when no RadioButton in the group is selected (the user has not picked a year yet). This matters because findViewById(-1) returns null, and calling .getText() on null crashes. So you must check if (id == -1) first and prompt the user to choose, before trusting the id. It is the RadioGroup version of validating that a required choice was actually made.
Quiz
Three RadioButtons let a user tick all three at once instead of just one. What is the most likely cause?
- They are not wrapped in a single RadioGroup
- They are missing the isChecked() method
- The RadioButtons need setChecked(true) in onCreate
- RadioButtons can never be mutually exclusive
Show the answer
They are not wrapped in a single RadioGroup
Mutual exclusion comes from the RadioGroup; without wrapping the buttons in one group they behave like independent checkboxes and all can be selected (A). isChecked() is a read method, not the cause (B). Calling setChecked in onCreate would just pre-select one, not enforce exclusion (C). RadioButtons are exactly the mutually-exclusive widget when grouped (D is false). The fix: put them all inside one RadioGroup.
Watch out
RadioButton traps
1. RadioButtons without a RadioGroup: they lose mutual exclusion and act like checkboxes. Always group them.
2. Not handling -1: getCheckedRadioButtonId() is -1 when nothing is chosen; findViewById(-1) is null. Check before use.
3. Splitting one choice across two groups: buttons in different RadioGroups are not exclusive with each other. Keep one logical choice in one group.
Theory
Next: dropdowns and dialogs
RadioButtons work well for a few options, but a long list (say, 12 T-shirt sizes or 50 colleges) is better as a dropdown. The next lesson pairs the Spinner (a dropdown picker) with the AlertDialog (a modal yes/no box) so FestConnect can pick a size and then confirm the registration before submitting.
Summary
Key takeaways
- RadioButtons let the user pick exactly one option, but only when wrapped in a RadioGroup (which enforces exclusion).
- Selecting one button in a group automatically clears the others.
- group.getCheckedRadioButtonId() returns the selected id, or -1 if none is chosen.
- findViewById(-1) is null, so check for -1 before reading the selected button.
- Use a RadioGroup for one-of-many; use CheckBoxes for many independent choices.
- Memory hook: old car radio buttons, one in pops the others out.