In Flutter, I have a simple dynamically generated Toggle buttons, but for some reason they are not changing color on being clicked. Button selection value is fine upon clicking as checked with print statements.
var responses = responseArray;
List<bool> isSelected = [];
List<Widget> ratingWidgets = [];
for (int i = 0; i < responses.length; i ) {
isSelected.add(false);
ratingWidgets.add(Text(responses[i].toString()));
}
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 15.0,
),
ToggleButtons(
borderRadius: const BorderRadius.all(Radius.circular(8)),
borderColor: Colors.blue,
selectedColor: Colors.green, // This is not happening
color: Colors.red,
isSelected: isSelected,
children: ratingWidgets,
direction: Axis.horizontal,
onPressed: (int index) {
setState(() {
for (int i = 0; i < isSelected.length; i ) {
isSelected[i] = i == index;
}
});
print(isSelected);
},
),
I also tried to use a method to generate color and set color variable, but that too didn't work, Where am I going wrong ?
Update:
Minimum Code to generate same error :
import 'package:flutter/material.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
void main() => runApp(MaterialApp(home: MyApp()));
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool spinnerRun = false;
List<List<String>> responseArray = [];
@override
void initState() {
responseArray.add(["Very good", "Good", "Poor", "Very Poor"]);
responseArray.add(["Good", "Better", "Best"]);
responseArray.add(["Yes", "No", "MayBe"]);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: ModalProgressHUD(
inAsyncCall: spinnerRun,
child: Column(
children: [
SizedBox(
height: 50.0,
),
for (int i = 0; i < 3; i ) getToggleButttonBars(responseArray[i])
],
),
),
);
}
getToggleButttonBars(List<String> responseArray) {
var responses = responseArray;
List<bool> isSelected = [];
List<Widget> ratingWidgets = [];
for (int i = 0; i < responses.length; i ) {
isSelected.add(false);
ratingWidgets.add(Text(responses[i].toString()));
}
return Padding(
padding: const EdgeInsets.all(8.0),
child: ToggleButtons(
borderRadius: const BorderRadius.all(Radius.circular(8)),
selectedBorderColor: Colors.green,
borderColor: Colors.blue,
selectedColor: Colors.green, // This is not happening
color: Colors.red,
isSelected: isSelected,
children: ratingWidgets,
direction: Axis.horizontal,
onPressed: (int index) {
setState(() {
for (int i = 0; i < isSelected.length; i ) {
isSelected[i] = i == index;
}
});
print(isSelected);
},
));
}
}
CodePudding user response:
The main issue is here putting selected holder inside the build method, it will reset to the default value on every build. I think it would be better to use map or model class instead, I am using List<List<bool>>
on state level for now.
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool spinnerRun = false;
List<List<String>> responseArray = [];
List<List<bool>> isSelected = [];
@override
void initState() {
super.initState();
responseArray.add(["Very good", "Good", "Poor", "Very Poor"]);
responseArray.add(["Good", "Better", "Best"]);
responseArray.add(["Yes", "No", "MayBe"]);
for (int i = 0; i < responseArray.length; i ) {
isSelected.add(List.generate(responseArray[i].length, (index) => false));
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: ModalProgressHUD(
inAsyncCall: spinnerRun,
child: Column(
children: [
SizedBox(
height: 50.0,
),
for (int i = 0; i < 3; i ) getToggleButttonBars(i)
],
),
),
);
}
getToggleButttonBars(int index) {
var responses = responseArray[index];
List<Widget> ratingWidgets = [];
for (int i = 0; i < responses.length; i ) {
ratingWidgets.add(Text(responses[i].toString()));
}
return Padding(
padding: const EdgeInsets.all(8.0),
child: ToggleButtons(
borderRadius: const BorderRadius.all(Radius.circular(8)),
selectedBorderColor: Colors.green,
borderColor: Colors.blue,
selectedColor: Colors.green,
color: Colors.red,
isSelected: isSelected[index],
children: ratingWidgets,
direction: Axis.horizontal,
onPressed: (int j) {
for (int i = 0; i < isSelected.length; i ) {
isSelected[index][i] = j == i;
}
setState(() {});
},
));
}
}