How do I add controllers to custom widgets in flutter

1,705

You can easily solve it by using a ChangeNotifier. That's actually also the way it's solved in TextFieldController and ScrollController.

I have some sample code for you based on what you described:

class SwitchController extends ChangeNotifier {
  bool isSwitchOn = false;

  void setValue(bool value) {
    isSwitchOn = value;
    notifyListeners();
  }
}

Now your widget that wraps the Switch:

class CustomSwitch extends StatefulWidget {
  CustomSwitch({
    required this.controller
  });

  final SwitchController controller;

  @override
  State<StatefulWidget> createState() {
    return _CustomSwitchState();
  }
}

class _CustomSwitchState extends State<CustomSwitch> {
  @override
  Widget build(BuildContext context) {
    return CupertinoSwitch(
      onChanged: (bool value) {
        widget.controller.setValue(value);
      },
      value: widget.controller.isSwitchOn,
    );
  }
}

Just listen to the change event of the native switch and set the value of the controller. Then notify the observers about it.

Then you can create the widget and pass a controller you add a listener to:

class SwitchTest extends StatefulWidget {
  @override
  _SwitchTestState createState() => _SwitchTestState();
}

class _SwitchTestState extends State<SwitchTest> {
  SwitchController controller = SwitchController();

  @override
  void initState() {
    controller.addListener(() {
      setState(() {
        print(controller.isSwitchOn);
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            CustomSwitch(
              controller: controller
            ),
            Text(controller.isSwitchOn.toString()),
          ],
        ),
      ),
    );
  }
}

I have written a detailed tutorial on how to create such custom controllers on my blog: https://www.flutterclutter.dev/flutter/tutorials/create-a-controller-for-a-custom-widget/2021/2149/

Share:
1,705
suma
Author by

suma

Updated on December 14, 2022

Comments

  • suma
    suma over 1 year

    I have a parent widget which calls a custom Switch widget that I've made. I need the value of the switch(whether it's ON or OFF) in my parent widget. Can I create a controller in my switch widget which would return that value?

    Currently, I am passing the function from my parent widget which changes the value of a boolean which is in my parent widget based on the value of the switch in the switch widget.

    Parent widget:

    bool isSwitchOn = false;
    Switch(onSwitchToggle: (bool val) {
                          isSwitchOn = val;
                      })
    

    Custom Switch widget:

    class Switch extends StatefulWidget {
     Widget build(BuildContext context) {
        return CupertinoSwitch(
            value: widget.value,
            onChanged: (bool value) {
              setState(() {
                widget.value = value;
              });
              widget.onSwitchToggle(value);
            },
    ),
    }
    

    The switch widget is used everywhere in the code whenever I need a switch and sometimes I don't need to know the state of the switch and I just need to execute a function when the switch is toggled but the way I've written the code, I'll need to pass bool everywhere whenever I call the switch. Looking for a better way to do it. eg: Bool val is unnecessary because i won't need it.

    Switch(onSwitchToggle: (bool val) {
                         print('abc')
                     })