Reputation: 6098
I've seen variations of this question but haven't been able to quite piece together a solution for my use case.
I have a list of CircleButton
.
List<CircleButton> buttons = [
new CircleButton(onTap: () => print("Arts"), iconData: Icons.palette, label: "Arts"),
new CircleButton(onTap: () => print("Board Games"), iconData: Icons.casino, label: "Board Games"),
new CircleButton(onTap: () => print("Causes"), iconData: Icons.volunteer_activism, label: "Causes"),
];
I display these in a GridView
Widget interests() {
return Expanded(
child:
SizedBox(
height: 200.0,
child:
GridView.count(
primary: false,
padding: const EdgeInsets.all(20),
crossAxisSpacing: 10,
mainAxisSpacing: 10,
crossAxisCount: 4,
children: <Widget>[
for (var button in buttons) Column( children: [ button, Text(button.label)],)
],
)
)
);
}
When the button is tapped I want to update how it looks. I have set up the CircleButton
class to have the boolean value isSelected
to determine how the coloring should be:
class CircleButton extends StatelessWidget {
final GestureTapCallback onTap;
final IconData iconData;
final String label;
bool isSelected = false;
CircleButton({Key key, this.onTap, this.iconData, this.label}) : super(key: key);
@override
Widget build(BuildContext context) {
double size = 65.0;
return new
InkResponse(
onTap: onTap,
child: new Container(
width: size,
height: size,
decoration: new BoxDecoration(
color: isSelected ? Color.fromRGBO(139, 207, 236, 1.0) : Color.fromRGBO(248, 248, 250, 1.0),
shape: BoxShape.circle,
),
child: new Icon(
iconData,
color: isSelected ? Colors.white : Color.fromRGBO(2, 78, 157, 1.0),
),
),
);
}
}
How can I update the isSelected
variable from onTap
?
Upvotes: 0
Views: 83
Reputation: 7819
If you want each button to manage its own selected state (meaning that tapping on a button will not unselect the others), you must use StatefulWidget :
class CircleButton extends StatefulWidget {
final GestureTapCallback onTap;
final IconData iconData;
final String label;
CircleButton({Key key, this.onTap, this.iconData, this.label})
: super(key: key);
@override
_CircleButtonState createState() => _CircleButtonState();
}
class _CircleButtonState extends State<CircleButton> {
bool isSelected = false;
@override
Widget build(BuildContext context) {
double size = 65.0;
return new InkResponse(
onTap: () {
widget.onTap;
// ADD THESE LINES
setState(() {
isSelected = !isSelected;
});
},
child: new Container(
width: size,
height: size,
decoration: new BoxDecoration(
color: isSelected
? Color.fromRGBO(139, 207, 236, 1.0)
: Color.fromRGBO(248, 248, 250, 1.0),
shape: BoxShape.circle,
),
child: new Icon(
widget.iconData,
color: isSelected ? Colors.white : Color.fromRGBO(2, 78, 157, 1.0),
),
),
);
}
}
Otherwise, if you want only one button to be selected at a time, juste create a variable in the parent widget that stores which button is selected :
int selectedButtonIndex;
List<CircleButton> buttons = [
new CircleButton(onTap: () {
print("Arts");
setState((){ selectedButtonIndex = selectedButtonIndex != 0 ? 0 : null; });
}, iconData: Icons.palette, label: "Arts",
isSelected: selectedButtonIndex == 0,
),
new CircleButton(onTap: () {
print("Board Games");
setState((){ selectedButtonIndex = selectedButtonIndex != 1 ? 1 : null; });
}, iconData: casino, label: "Board Games",
isSelected: selectedButtonIndex == 1,
),
...
];
And add isSelected
as a parameter for CircleButton
Upvotes: 2