The Material widgets `Switch`, `SwitchListTile`, `Checkbox`, `CheckboxListTile`, `Radio`, `RadioListTile` now use `ColorScheme.secondary` color for their toggleable widget. `ThemeData.toggleableActiveColor` is deprecated and will eventually be removed.
Original behavior
The migration of widgets that depend on `ThemeData.toggleableActiveColor` to `ColorScheme.secondary` caused the `toggleableActiveColor` property to be unnecessary. This property will eventually be removed, as per Flutter's deprecation policy.
New behavior
The widgets using `ThemeData.toggleableActiveColor` color for the active/selected state now use `ColorScheme.secondary`.
- Who is affected
- Code that still calls the deprecated API; it keeps working until removal but produces analyzer warnings. Code that uses Switch, SwitchListTile, Checkbox and related APIs.
- Practical impact
- Warnings now; removal in a future release. Plan the migration but no immediate break.
- What action should I take?
- Follow the official migration guide below, update affected call sites, run `dart fix --apply` where a fix is available, then run your tests.
Before and after (from the official guide)
| 1 | MaterialApp( | |
| 2 | − | theme: ThemeData(toggleableActiveColor: myColor), |
| 3 | − | // ... |
| 4 | − | ); |
| 1 | + | final ThemeData theme = ThemeData(); |
| 2 | MaterialApp( | |
| 3 | + | theme: theme.copyWith( |
| 4 | + | switchTheme: SwitchThemeData( |
| 5 | + | thumbColor: MaterialStateProperty.resolveWith<Color?>( |
| 6 | + | (Set<MaterialState> states) { |
| 7 | + | if (states.contains(MaterialState.disabled)) { |
| 8 | + | return null; |
| 9 | + | } |
| 10 | + | if (states.contains(MaterialState.selected)) { |
| 11 | + | return myColor; |
| 12 | + | } |
| 13 | + | return null; |
| 14 | + | }), |
| 15 | + | trackColor: MaterialStateProperty.resolveWith<Color?>( |
| 16 | + | (Set<MaterialState> states) { |
| 17 | + | if (states.contains(MaterialState.disabled)) { |
| 18 | + | return null; |
| 19 | + | } |
| 20 | + | if (states.contains(MaterialState.selected)) { |
| 21 | + | return myColor; |
| 22 | + | } |
| 23 | + | return null; |
| 24 | + | }), |
| 25 | + | ), |
| 26 | + | radioTheme: RadioThemeData( |
| 27 | + | fillColor: MaterialStateProperty.resolveWith<Color?>( |
| 28 | + | (Set<MaterialState> states) { |
| 29 | + | if (states.contains(MaterialState.disabled)) { |
| 30 | + | return null; |
| 31 | + | } |
| 32 | + | if (states.contains(MaterialState.selected)) { |
| 33 | + | return myColor; |
| 34 | + | } |
| 35 | + | return null; |
| 36 | + | }), |
| 37 | + | ), |
| 38 | + | checkboxTheme: CheckboxThemeData( |
| 39 | + | fillColor: MaterialStateProperty.resolveWith<Color?>( |
| 40 | + | (Set<MaterialState> states) { |
| 41 | + | if (states.contains(MaterialState.disabled)) { |
| 42 | + | return null; |
| 43 | + | } |
| 44 | + | if (states.contains(MaterialState.selected)) { |
| 45 | + | return myColor; |
| 46 | + | } |
| 47 | + | return null; |
| 48 | + | }), |
| 49 | + | ), |
| 50 | + | ), |
| 51 | + | //... |
| 52 | + | ) |
Raw before / after
MaterialApp( theme: ThemeData(toggleableActiveColor: myColor), // ... );
final ThemeData theme = ThemeData();
MaterialApp(
theme: theme.copyWith(
switchTheme: SwitchThemeData(
thumbColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return null;
}
if (states.contains(MaterialState.selected)) {
return myColor;
}
return null;
}),
trackColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return null;
}
if (states.contains(MaterialState.selected)) {
return myColor;
}
return null;
}),
),
radioTheme: RadioThemeData(
fillColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return null;
}
if (states.contains(MaterialState.selected)) {
return myColor;
}
return null;
}),
),
checkboxTheme: CheckboxThemeData(
fillColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return null;
}
if (states.contains(MaterialState.selected)) {
return myColor;
}
return null;
}),
),
),
//...
)Official migration guide (excerpt, © The Flutter Authors, CC BY 3.0)
Toggleable widgets' active/selected color can generally be customized in 3 ways:
- Using ThemeData's
ColorScheme.secondary. - Using components themes
SwitchThemeData,ListTileThemeData,CheckboxThemeData, andRadioThemeData. - By customizing the widget's color properties.
Code before migration:
MaterialApp(
theme: ThemeData(toggleableActiveColor: myColor),
// ...
);Code after migration:
final ThemeData theme = ThemeData();
MaterialApp(
theme: theme.copyWith(
switchTheme: SwitchThemeData(
thumbColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return null;
}
if (states.contains(MaterialState.selected)) {
return myColor;
}
return null;
}),
trackColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return null;
}
if (states.contains(MaterialState.selected)) {
return myColor;
}
return null;
}),
),
radioTheme: RadioThemeData(
fillColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return null;
}
if (states.contains(MaterialState.selected)) {
return myColor;
}
return null;
}),
),
checkboxTheme: CheckboxThemeData(
fillColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return null;
}
if (states.contains(MaterialState.selected)) {
return myColor;
}
return null;
}),
),
),
//...
)AI_PROVIDER (for example to openai-compatible with a local Ollama or LM Studio endpoint) to enable grounded explanations. Everything else on this page works without an AI provider.Listed in the official breaking-changes index; title states deprecation.
An official announcement or migration guide documents an intended behaviour or API change. A verified source change (git diff) shows code changed but does not by itself prove a public API is breaking. AI interpretations are labelled and never used to classify a change.
- Source commit
- b3045439b7c0
- Source last updated
- Oct 21, 2026
- Last synchronized
- Oct 21, 2026
- Publication status
- published
Publication history
- Oct 21, 2026, 8:31 PM: new → published (ingestion) — Backed by an official breaking-change/migration guide.
AI_PROVIDER (for example to openai-compatible with a local Ollama or LM Studio endpoint) to enable grounded explanations. Everything else on this page works without an AI provider.