Flutter 2 - 设置自动完成 TextFormField 的初始值

Posted

技术标签:

【中文标题】Flutter 2 - 设置自动完成 TextFormField 的初始值【英文标题】:Flutter 2 - Set initial value of an Autocomplete TextFormField 【发布时间】:2021-06-19 23:56:27 【问题描述】:

我不能使用TextEditingController,因为TextFormField使用AutocompletefieldViewBuilderTextEditingController

Autocomplete(
                optionsBuilder: (TextEditingValue textEditingValue) 
                  if (textEditingValue.text == '') return [];

                  return this
                      .productNames
                      .where((Map<String, dynamic> option) 
                    return option['ar']
                        .toLowerCase()
                        .contains(textEditingValue.text.toLowerCase());
                  );
                ,
                fieldViewBuilder: (context, textEditingController,
                        focusNode, onFieldSubmitted) =>
                    TextFormField(                             
                  controller: textEditingController,//uses fieldViewBuilder TextEditingController
                   focusNode: focusNode,
                ),
              ),

【问题讨论】:

【参考方案1】:

编辑

我刚刚意识到您正在使用 TextFormField,它有一个名为 initialValue 的参数。如果您不需要文本编辑控制器,这个答案应该可以工作

fieldViewBuilder: (context, textEditingController,
                        focusNode, onFieldSubmitted) =>
                    TextFormField(                             
             
                   focusNode: focusNode,
                   initialValue:"Your initial Value",
                ),

或者如果你正在使用你的控制器试试

fieldViewBuilder: (context, textEditingController,
                        focusNode, onFieldSubmitted) =>
                    TextFormField(                             
                  controller: textEditingController..text="Initial Value",
                   focusNode: focusNode,
                ),

原始答案

您为什么不使用该文本编辑控制器本身。代码将是这样的

Autocomplete(
                optionsBuilder: (TextEditingValue textEditingValue) 
                  if (textEditingValue.text == '') return [];

                  return this
                      .productNames
                      .where((Map<String, dynamic> option) 
                    return option['ar']
                        .toLowerCase()
                        .contains(textEditingValue.text.toLowerCase());
                  );
                ,
                fieldViewBuilder: (context, textEditingController,
                        focusNode, onFieldSubmitted)
                    textEditingController.text  = "Your initial text";// You can use the next snip of code if you dont want the initial text to come when you use setState(());  
                    return TextFormField(                             
                  controller: textEditingController,//uses fieldViewBuilder TextEditingController
                   focusNode: focusNode,
                ),
               
              ),

如果您正在使用 setState 并且上面的代码段不断将文本替换为初始文本,请执行类似的操作

Autocomplete(
                optionsBuilder: (TextEditingValue textEditingValue) 
                  if (textEditingValue.text == '') return [];

                  return this
                      .productNames
                      .where((Map<String, dynamic> option) 
                    return option['ar']
                        .toLowerCase()
                        .contains(textEditingValue.text.toLowerCase());
                  );
                ,
                fieldViewBuilder: (context, textEditingController,
                        focusNode, onFieldSubmitted)
                    textEditingController.text = textEditingController.text  == ""? "Inital Text":textEditingController.text;// You can use the next snip of code if you dont want the initial text to come when you use setState(());  
                    return TextFormField(                             
                  controller: textEditingController,//uses fieldViewBuilder TextEditingController
                   focusNode: focusNode,
                ),
               
              ),

最后一个解决方案不太优雅,但很有效。如果我找到更好的解决方案,我会告诉你。您甚至可以将此 textEditingController 分配给在顶部声明的全局变量,并从代码中的任何位置访问它。而不是检查文本是否为空,而是在每次 setState 时增加一个新变量的值,如果值为 == 0,则可以设置初始文本

【讨论】:

这是我目前正在使用的.. 但是每次我更改初始值并调用 setState() 。我收到以下错误。它确实有效,但由于这个错误,我认为它不是正确的方法。 在为 TextEditingController 发送通知时引发以下断言: 在构建期间调用了 setState() 或 markNeedsBuild()。 我不完全确定为什么会针对您的项目抛出此错误,我将不得不查看代码文件,但调用它的原因是因为您调用 setState() 方法过早没有完成构建。该错误无关紧要,因为构建会立即完成,因此可以运行更改 我已经从 Autocomplete() 中注释掉了 textEditingController.text = "Your initial text"; 。当我调用setState() 时,它不会抛出任何错误 我猜更改文本将重建文本字段,这将导致无限循环。尝试在顶部设置一个计数器变量并将其设置为 0。然后在构建器中,检查计数器变量是否为 0。如果为 0,则设置初始文本(它可能会重建它,但只能重建一次)并将其添加到计数器变量。也许在延迟的异步函数中分配初始文本 @ibrahimxcool 我刚刚添加了 2 种新方法。如果您不需要控制器,请尝试第一个,如果您需要控制器,请尝试第二个【参考方案2】:

AutoComplete 对此有一个命名参数 initialValue

Autocomplete<AutocompletePrediction>(  
    initialValue: const TextEditingValue(text: "Initial value"),  
    fieldViewBuilder: ...
    ...  
)  

【讨论】:

【参考方案3】:

这是我为TextFormField 找到的解决方案。确保控制器在帧结束时更新。

fieldViewBuilder: (BuildContext context,
  TextEditingController fieldTextEditingController,
  FocusNode fieldFocusNode,
  VoidCallback onFieldSubmitted) 

  SchedulerBinding.instance?.addPostFrameCallback((_)  // <--- this part
    var initialValue = someValueThatGotUpdatedDuringBuild;

    fieldTextEditingController.text = initialValue;
  );
  return TextFormField(...);

...

【讨论】:

@thenoobslayer,见上文,如果您仍有问题,可能会解决您的问题。 这对我有用,但在较新版本的 Flutter 中它应该是 `WidgetsBinding.instance.addPostFrameCallback((_) `

以上是关于Flutter 2 - 设置自动完成 TextFormField 的初始值的主要内容,如果未能解决你的问题,请参考以下文章

Flutter/Dart 自动完成功能适用于 VS Code,但不适用于 Android Studio

Flutter:FormBuilderDropdown 自动完成

Flutter 自动完成功能在 VSCode 中无法用于包

如何从自动完成小部件 Flutter 中使用 TextEditingController

Flutter TextField 自动完成覆盖

自动完成/智能感知不适用于 VSCode 中的 dart/flutter