fluttermobilecheckboxstate-management

Logic dont working on a custom Checkbox Widget


The logic of my custom CheckBox does not work like the material's default CheckBox, what can I do to solve this?

Here I have a column with two Material's Checkbox, the logic behind them is: as soon as one is checked, the other is automatically unchecked

Column(
            children: [
              SizedBox(
                width: screenSize.width * .38,
                height: screenSize.height * .07,
                child: CardBox(
                  shadowSize: 2,
                  customRadius: const [10, 10],
                  boxContent: Row(
                    children: [
                      Transform.scale(
                        scale: 1.3,
                        child: Checkbox(
                          value: bool1Selected,
                          activeColor: widget.color,
                          checkColor: widget.color,
                          onChanged: (newBool) {
                            setState(() {
                              bool2Selected= false;
                              bool1Selected= newBool;
                            });
                          },
                        ),
                      ),
                      const SizedBox(
                        width: 5,
                        height: 1,
                      ),
                      Text('Spain',
                          style: const TextStyle(
                            fontSize: 35,
                            ),
                          ))
                    ],
                  ),
                ),
              ),
              SizedBox(
                width: screenSize.width * .38,
                height: screenSize.height * .02,
              ),
              SizedBox(
                width: screenSize.width * .38,
                height: screenSize.height * .07,
                child: CardBox(
                  shadowSize: 2,
                  customRadius: const [10, 10],
                  boxContent: Row(
                    children: [
                      Transform.scale(
                        scale: 1.3,
                        child: Checkbox(
                          value: bool2Selected,
                          activeColor: widget.color,
                          checkColor: widget.color,
                          onChanged: (newBool) {
                            setState(() {
                              bool1Selected = false;
                              bool2Selected = newBool;
                            });
                          },
                        ),
                      ),
                      const SizedBox(
                        width: 5,
                        height: 1,
                      ),
                      Text(
                        'EUA',
                        style: const TextStyle(
                          fontSize: 35,
                          
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),

With this code above, it is working, however I made a custom CheckBbox to better serve my purpose, but as soon as I click on one CheckBox the other is not unchecked. Follow the code below:

class _CustomCheckboxState extends State<CustomCheckbox> {
  Color borderColor = ThemeColors.cardHighlight;
  bool isChecked = false;

  @override
  void initState() {
    super.initState();
    isChecked = widget.isChecked;
  }

  @override
  Widget build(BuildContext context) {
    var screenSize = MediaQuery.of(context).size;

    return InkWell(
      child: Container(
        width: screenSize.width * .35,
        height: screenSize.height * .07,
        decoration: BoxDecoration(
          color: ThemeColors.cardHighlight,
          boxShadow: kElevationToShadow[3],
          borderRadius: const BorderRadius.all(Radius.circular(10)),
          border: Border.all(
            width: 6,
            strokeAlign: BorderSide.strokeAlignInside,
            color: isChecked ? borderColor = widget.borderColor : borderColor = ThemeColors.cardHighlight,
          ),
        ),
        child: Center(
          child: Text(
            widget.text,
            style: TextStyle(fontSize: 35),
          ),
        ),
      ),
      onTap: () {
        setState(
          () {
            isChecked = !isChecked;
            widget.onChange(isChecked);
          },
        );
      },
    );
  }
}

I tried to analyze the Material CheckBox source code, but a lot of things there like state management I'm still trying to learn in flutter, could anyone please tell me how to fix this problem?


Solution

  • Even though you are passing correct updated value to the CustomCheckbox and setting it inside initState which is is working as expected. The initState will only called once while creating the widget, rest things updated from state class.

    In order to update the state class, you can override didUpdateWidget

      @override
      void didUpdateWidget(covariant CustomCheckbox oldWidget) {
        super.didUpdateWidget(oldWidget);
        isChecked = widget.isChecked;
        // setState(() {});
      }
    

    Also I would prefer just using Stateless widget based on your current snippet.

    And for the logic, use negative value on onChaged

    text: "Text 1",
    onChange: (bool value) {
      setState(() {
        bool1Selected = value;
        bool2Selected = !bool1Selected;
      });
    },
    

    same way for next one

    text: "Text 2",
    onChange: (bool value) {
      setState(() {
        bool2Selected = value;
        bool1Selected = !bool2Selected;
      });
    },