首页 > 解决方案 > Flutter:如何从自定义 StatefulWidget 中的 TextEditingController 检索文本?

问题描述

我正在尝试使自定义有状态小部件在颤动中工作。它称为 LetterTextForm,包含一些布局自定义和一个 TextField。

我希望很容易检索输入到小部件的 TextField 中的文本,在小部件主体中使用某种返回 TextEditingController.text 的 getter 方法。问题是,当我使 TextEditingController 控制器成为这样的最终变量时:

class LetterTextForm extends StatefulWidget {

  LetterTextForm({@required this.label, this.prefixIcon});
  final Widget prefixIcon;
  final String label;
  final TextEditingController controller = TextEditingController();
  String get textEntered => controller.text;


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

class _LetterTextFormState extends State<LetterTextForm> {
  

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
  controller.dispose();
    super.dispose();
  }


  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: widget.controller,
        decoration: InputDecoration(
          prefixIcon: widget.prefixIcon,
          labelText: widget.label,
        )
    );
  }
}


抛出以下错误:“处理后使用了 TextEditingController。”

我想也许问题是控制器不应该是最终的,所以我将控制器移到状态类中并在状态类中创建了一个函数 textCallback,它修改了小部件类中的非最终字符串。这种方式有效但违反了小部件的不变性:


class LetterTextForm extends StatefulWidget {

  LetterTextForm({@required this.label, this.prefixIcon});
  final Widget prefixIcon;
  final String label;
  String text = '';

  String get textEntered => text;



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

class _LetterTextFormState extends State<LetterTextForm> {
  var controller = TextEditingController();
  
  void textCallback() {
    widget.text = controller.text;
  }

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
  controller.dispose();
    super.dispose();
  }


  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: controller,
        decoration: InputDecoration(
          prefixIcon: widget.prefixIcon,
          labelText: widget.label,
        )
    );
  }
}


有没有办法做到这一点,1)不违反不变性和 2)当用户点击 Enter 时不立即处理 TextEditingController()?

当我摆脱 dispose() 方法时它会起作用,但这似乎会在以后导致一些性能/内存效率问题。也许我不知道我在说什么...

也许我应该尝试一些完全不同的东西,并将 TextEditingControllers 放置在具有 LetterTextForm 小部件的祖先的树中,而不是在小部件内部?

标签: flutterdarttextfielddispose

解决方案


创建ValueChanged<String>回调成员,数据完成后回调。

class LetterTextForm{
  ...
  final ValueChanged<String> onChanged;
  ...
}

class _LetterTextFormState extends ... {
  final _controller = TextEditingController();
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(...) {
    return TextField(
      controller: _controller,
      onSubmitted: (value) {
        if (widget.onChanged != null) {
          widget.onChanged(value); // returns entered value to caller
        }
      },
    );
  }
}

PS 如果要使用TextFormField,则不需要控制器,您可以initialData用于初始化。


推荐阅读