繁体   English   中英

Flutter overlayEntry 在 state 更改后不更新内容

[英]Flutter overlayEntry doesn't update content after state change

我正在尝试为显示某些特定 state 的文本字段实现覆盖 function,具体取决于用户输入的内容。 当用户点击文本字段时,它会显示一个叠加层,在用户书写时应该显示一些信息,就像 web 浏览器上的搜索栏一样。

我的问题是 OverlayEntry 的内容不会在用户输入更改的同时更新,它只会在我重新打开 Overlay 时更改。

预期行为

在此处输入图像描述

当前行为

在此处输入图像描述

为了测试此功能,我只是将相同的值从文本字段传递到叠加层。

这是我的代码:

主页 class

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
        child: Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  CustomTextField(),
                ]),
            // This trailing comma makes auto-formatting nicer for build methods.
          ),
        ));
  }
}

自定义文本字段 class:

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

  @override
  State<CustomTextField> createState() => _CustomTextFieldState();
}

class _CustomTextFieldState extends State<CustomTextField>
    with TickerProviderStateMixin {
  TextEditingController controlador = TextEditingController();
  FocusNode nodeUno = FocusNode();
  OverlayEntry? _overlayEntry;
  GlobalKey globalKey = GlobalKey();
  final LayerLink _layerLink = LayerLink();
  String inputText = '';

  @override
  void initState() {
    super.initState();
    OverlayState? overlayState = Overlay.of(context);
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      globalKey;
    });

    nodeUno.addListener(() {
      if (nodeUno.hasFocus) {
        _overlayEntry = _createOverlay(inputText);

        overlayState!.insert(_overlayEntry!);
      } else {
        _overlayEntry!.remove();
      }
    });
  }

  OverlayEntry _createOverlay([String? text]) {
    RenderBox renderBox = context.findRenderObject() as RenderBox;

    var size = renderBox.size;
    return OverlayEntry(
        builder: (context) => Positioned(
              width: size.width,
              child: CompositedTransformFollower(
                link: _layerLink,
                showWhenUnlinked: false,
                offset: Offset(0.0, size.height + 5.0),
                child: Material(
                  elevation: 5.0,
                  child: Column(
                    children: [
                      ListTile(
                        title: text != '' ? Text(text!) : const Text('data'),
                      ),
                    ],
                  ),
                ),
              ),
            ));
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 250,
      child: CompositedTransformTarget(
        link: _layerLink,
        child: TextField(
          focusNode: nodeUno,
          controller: controlador,
          onChanged: (value) {
            print(value);
            setState(() {
              inputText = value;
            });
          },
        ),
      ),
    );
  }
}

好吧,据我所知,更新覆盖条目内容的唯一方法是删除并再次插入该条目,所以这就是我发现的有效方法:

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

  @override
  State<CustomTextField> createState() => _CustomTextFieldState();
}

class _CustomTextFieldState extends State<CustomTextField>
    with TickerProviderStateMixin {
  TextEditingController controlador = TextEditingController();
  FocusNode nodeUno = FocusNode();
  OverlayEntry? _overlayEntry;
  GlobalKey globalKey = GlobalKey();
  final LayerLink _layerLink = LayerLink();
  String inputText = '';
  OverlayState? overlayState;
  bool popoverOpened = false;

  @override
  void initState() {
    super.initState();
    _overlayEntry = null;
    overlayState = Overlay.of(context);
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      globalKey;
    });

    nodeUno.addListener(() {
      if (nodeUno.hasFocus) {
        _overlayEntry = _createOverlay(inputText);
        overlayState!.insert(_overlayEntry!);
      } else {
        if (_overlayEntry != null) {
          _overlayEntry?.remove();
          _overlayEntry = null;
        }
      }
    });
  }

  OverlayEntry _createOverlay([String? text]) {
    RenderBox renderBox = context.findRenderObject() as RenderBox;

    if (_overlayEntry != null && popoverOpened) {
      _overlayEntry!.remove();
    }
    popoverOpened = true;
    var size = renderBox.size;
    return OverlayEntry(
        builder: (context) => Positioned(
              width: size.width,
              child: CompositedTransformFollower(
                link: _layerLink,
                showWhenUnlinked: false,
                offset: Offset(0.0, size.height + 5.0),
                child: OverlayClass(val: inputText),
              ),
            ));
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 250,
      child: CompositedTransformTarget(
        link: _layerLink,
        child: TextField(
          focusNode: nodeUno,
          controller: controlador,
          onChanged: (value) {
            print(value);
            setState(() {
              inputText = value;
              _overlayEntry = _createOverlay(inputText);
              overlayState!.insert(_overlayEntry!);
            });
          },
        ),
      ),
    );
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM