dart - Flutter:CheckBox 在 OverlayEntry 中不起作用?

标签 dart flutter

我正在尝试在 OverlayEntry 中显示一些小部件,例如 CheckBox 或 Switch。叠加层是在点击事件中构建的。 问题是 bool _value 仅在我第一次点击叠加层内的 CheckBox 时更新,但 CheckBox 不会更新其状态。奇怪的是(只有第一次点击)点击会更新覆盖层外的 CheckBox 而不是覆盖层内的 CheckBox。 我在这里错过了什么?

下面是一个完整的片段来重现这一点。

感谢您的宝贵时间!

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _value = true;

  _buildOverlay() {
    OverlayEntry _overlayEntry;
    OverlayState _overlayState = Overlay.of(context);

    _overlayEntry = OverlayEntry(
      builder: (BuildContext context) {
        return Stack(
          children: <Widget>[
            Material(
              child: Container(
                padding: EdgeInsets.all(100),
                color: Colors.lightBlue,
                child: Checkbox(
                  value: _value,
                  onChanged: (bool value) { print("$value  $_value"); setState(() => _value = value); },
                ),
              ),
            ),
          ],
        );
      },
    );

    _overlayState.insert(_overlayEntry);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(""),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Row(
              children: <Widget>[
                FloatingActionButton(
                  onPressed: () {_buildOverlay();},
                  child: Icon(Icons.add),
                ),
                Checkbox(
                  value: _value,
                  onChanged: (bool value) { print("$value  $_value"); setState(() => _value = value); },
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

更新:

除了 anmol.majhail 解决方案,使用 ValueListenableBuilder可能是无需执行 StatefulWidget 的另一种解决方案。

_value的声明变成: var _value = ValueNotifier<bool>(false);

这里是 _buildOverlay() 函数中的 _overlayEntry:

_overlayEntry = OverlayEntry(
      builder: (BuildContext context) {
        return Material(
          child: Container(
            padding: EdgeInsets.all(100),
            color: Colors.lightBlue,
            child: ValueListenableBuilder<bool>(
              valueListenable: _value,
              builder: (context, value, child) {
                return Checkbox(
                    value: _value.value,
                    onChanged: (bool value) { 
                      print("$value  $_value"); 
                      setState(() => _value.value = value); 
                    },
                  );
              },
            ),
          ),
        );
      },
    );

最佳答案

这里的问题是 Overlay entry 有不同的上下文。为了使其正常工作,您需要将 overlay entry 分离到一个单独的 stateful 小部件中 - 通过它您可以管理 checkbox 状态。

工作代码:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _value = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(""),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Row(
              children: <Widget>[
                FloatingActionButton(
                  onPressed: () {
                    OverlayState _overlayState = Overlay.of(context);
                    _overlayState.insert(OverlayEntry(
                      builder: (BuildContext context) {
                        return OverlayClass(
                          val: _value,
                        );
                      },
                    ));
                    // _buildOverlay(context);
                  },
                  child: Icon(Icons.add),
                ),
                Checkbox(
                  value: _value,
                  onChanged: (bool value) {
                    print("$value  $_value");
                    setState(() => _value = value);
                  },
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

class OverlayClass extends StatefulWidget {
  final bool val;

  OverlayClass({this.val});

  @override
  _OverlayClassState createState() => _OverlayClassState();
}

class _OverlayClassState extends State<OverlayClass> {
  bool _value;
  @override
  void initState() {
    super.initState();
    _value = widget.val;
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Material(
          child: Container(
            padding: EdgeInsets.all(100),
            color: Colors.lightBlue,
            child: Checkbox(
              value: _value,
              onChanged: (bool value) {
                print("$value  $_value");
                setState(() => _value = value);
              },
            ),
          ),
        ),
      ],
    );
  }
}

关于dart - Flutter:CheckBox 在 OverlayEntry 中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55386957/

相关文章:

flutter - 为什么一个对象在它的声明之后被实例化?

flutter - 如何将 List 的每一项与 ListView 构建器的每一项进行比较?

firebase - 如何使用flutter搜索用户数据并从Firebase检索用户数据?

flutter - 元素类型 'List<Card>' 无法分配给列表类型 'Widget'

flutter - 如何使下拉按钮创建的列表形状呈圆形?

dart - 在 Dart 中,使用 'new' 关键字和直接调用构造函数有什么区别?

flutter - 需要帮助在 Flutter 中导入自定义图标

json - 将多行字符串从文本字段保存到 JSON 文件

firebase - flutter firebase 使用 future 从数据库获取字符串

listview - 如何在 flutter 中将 ListView 滚动到底部