Sara Fuerst
Sara Fuerst

Reputation: 6098

Flutter: Changing color on button press of class in List

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

Answers (1)

Augustin R
Augustin R

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

Related Questions