如何在Flutter中为自定义小部件添加控制器

6

我有一个调用自定义Switch小部件的父部件。我需要在父部件中获取开关值(开或关)。我能否在我的Switch小部件中创建控制器来返回该值?

目前,我正在通过函数从父部件传递来更改布尔值的值(该值基于Switch小部件中的值),该布尔值位于我的父部件中。

父部件:

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

自定义开关小部件:

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

每当我需要一个开关时,代码中无处不用到switch小部件。有时候我不需要知道开关的状态,只是需要在切换开关时执行一个函数,但是按照我的写法,每次调用开关时都需要传递bool值。希望能找到更好的方法。

例如:因为我不需要val布尔值,所以它变得没有必要。

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

您可以使用GlobalKey(),并获取类似这样的状态。this.globalkey.currentState.isSwitchOn。 - Akio Alex
1
控制器的存在不就是为了避免使用GlobalKey()吗? - CiriousJoker
1
你解决了吗,@suma? - Fernando Santos
1个回答

4

您可以通过使用ChangeNotifier轻松解决它。这实际上也是在TextFieldController和ScrollController中解决它的方式。

我根据您描述的内容为您提供了一些示例代码:

class SwitchController extends ChangeNotifier {
  bool isSwitchOn = false;

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

现在您的小部件包装开关:
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,
    );
  }
}

只需监听原生开关的更改事件,设置控制器的值。然后通知观察者即可。

接着,您可以创建小部件,并传递一个已添加监听器的控制器:

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()),
          ],
        ),
      ),
    );
  }
}

我在博客里写了一份详细的教程,介绍如何创建自定义控制器。链接如下:https://www.flutterclutter.dev/flutter/tutorials/create-a-controller-for-a-custom-widget/2021/2149/

谢谢你的回复。我根据你提供的代码链接,使用了SwitchListTile来创建了自己的版本。不知为何,在我加入了状态的setState( ... )之后,我的代码才能正常工作。你认为这样做是必要的吗?这是在第27行。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接