【问题标题】:How do you change the value inside of a textfield flutter?如何更改文本字段颤动中的值?
【发布时间】:2018-12-10 03:42:17
【问题描述】:

我有一个TextEditingController,如果用户点击一个按钮,它会填写信息。我似乎不知道如何更改 TextfieldTextFormField 中的文本。有解决办法吗?

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    只需更改text 属性

        TextField(
          controller: txt,
        ),
        RaisedButton(onPressed: () {
            txt.text = "My Stringt";
        }),
    

    txt 只是TextEditingController

      var txt = TextEditingController();
    

    【讨论】:

    • 使用此代码将光标移到字段的左侧。有什么办法解决吗?
    • @rickdroio 查看this answer,它会将光标放在末尾。
    • @rickdroio 是的,下面的评论stackoverflow.com/a/58307018/7691350
    • 所以我必须为要数据绑定的每个输入添加一个 TextEditingController?
    【解决方案2】:

    只是设置的问题

    _controller.text = "New value";
    

    是光标将重新定位到开头(在材料的TextField中)。使用

    _controller.text = "Hello";
    _controller.selection = TextSelection.fromPosition(
        TextPosition(offset: _controller.text.length),
    );
    setState(() {});
    

    效率不高,因为它重新构建小部件的次数超出了必要的程度(在设置 text 属性和调用 setState 时)。

    --

    我认为最好的方法是将所有内容组合成一个简单的命令:

    final _newValue = "New value";
    _controller.value = TextEditingValue(
          text: _newValue,
          selection: TextSelection.fromPosition(
            TextPosition(offset: _newValue.length),
          ),
        );
    

    它适用于 Material 和 Cupertino 文本字段。

    【讨论】:

    • 这应该是正确的答案,因为它处理了更改控制器值和光标一直回到文本开头的问题
    • 还有一个建议,在提供偏移量的时候,我们可以这样做: int currentOffset = _textEditingController.selection.base.offset;然后提供 currentOffset 作为偏移量。这也将处理用户在字符串之间的情况。
    【解决方案3】:

    您可以使用文本编辑控制器来操作文本字段中的值。

    var textController = new TextEditingController();
    

    现在,创建一个新的文本字段并将textController 设置为文本字段的控制器,如下所示。

     new TextField(controller: textController)
    

    现在,在代码中的任意位置创建一个RaisedButton,并在RaisedButtononPressed 方法中设置所需的文本。

    new RaisedButton(
           onPressed: () {
              textController.text = "New text";
           }
        ),
    

    【讨论】:

    • TextField的文本修改不需要调用setState
    【解决方案4】:

    截图:

    1. 创建TextEditingController

      final TextEditingController _controller = TextEditingController();
      
    2. 将其分配给您的TextFieldTextFormField

      TextField(controller: _controller)
      
    3. 使用光标位置的按钮更新文本(假设文本字段中已经有文本):

      ElevatedButton(
        onPressed: () {
          const newText = 'Hello World';
          final updatedText = _controller.text + newText;
          _controller.value = _controller.value.copyWith(
            text: updatedText,
            selection: TextSelection.collapsed(offset: updatedText.length),
          );
        },
      )
      

    【讨论】:

      【解决方案5】:
      _mytexteditingcontroller.value = new TextEditingController.fromValue(new TextEditingValue(text: "My String")).value;
      

      如果有人有更好的方法,这似乎可行,请随时告诉我。

      【讨论】:

      • 怎么样:_mytexteditingcontroller.text="你的文字"
      • 如果你想创建一个已经填写了值的 TextField 就完美了:)
      【解决方案6】:

      第一件事

        TextEditingController MyController= new TextEditingController();
      

      然后将其添加到 init State 或任何 SetState 中

          MyController.value = TextEditingValue(text: "ANY TEXT");
      

      【讨论】:

        【解决方案7】:

        如果您只是想替换文本编辑控制器中的整个文本,那么这里的其他答案也可以。但是,如果您想以编程方式插入、替换选择或删除,则需要更多代码。

        制作您自己的自定义键盘是其中一个用例。下面的所有插入和删除都是以编程方式完成的:

        插入文字

        这里的_controllerTextEditingControllerTextField

        void _insertText(String myText) {
          final text = _controller.text;
          final textSelection = _controller.selection;
          final newText = text.replaceRange(
            textSelection.start,
            textSelection.end,
            myText,
          );
          final myTextLength = myText.length;
          _controller.text = newText;
          _controller.selection = textSelection.copyWith(
            baseOffset: textSelection.start + myTextLength,
            extentOffset: textSelection.start + myTextLength,
          );
        }
        

        感谢 this Stack Overflow answer 对此的帮助。

        删除文字

        有几种不同的情况需要考虑:

        1. 有一个选择(删除选择)
        2. 光标在开头(不要做任何事情)
        3. 其他(删除前一个字符)

        这里是实现:

        void _backspace() {
          final text = _controller.text;
          final textSelection = _controller.selection;
          final selectionLength = textSelection.end - textSelection.start;
        
          // There is a selection.
          if (selectionLength > 0) {
            final newText = text.replaceRange(
              textSelection.start,
              textSelection.end,
              '',
            );
            _controller.text = newText;
            _controller.selection = textSelection.copyWith(
              baseOffset: textSelection.start,
              extentOffset: textSelection.start,
            );
            return;
          }
        
          // The cursor is at the beginning.
          if (textSelection.start == 0) {
            return;
          }
        
          // Delete the previous character
          final newStart = textSelection.start - 1;
          final newEnd = textSelection.start;
          final newText = text.replaceRange(
            newStart,
            newEnd,
            '',
          );
          _controller.text = newText;
          _controller.selection = textSelection.copyWith(
            baseOffset: newStart,
            extentOffset: newStart,
          );
        }
        

        完整代码

        你可以在我的文章Custom In-App Keyboard in Flutter中找到完整的代码和更多的解释。

        【讨论】:

        • 我正在使用这段代码,它基本上是在 textField 的值不为 null 时在开始时添加值,但问题是当它在光标的输入位置更改并开始在值之前写入时添加 $ 符号时如果之前的值为 1 美元,那么它会写入 2 美元。那么这项任务有什么解决方案或更好的逻辑吗? "onChanged: (value) { if (dollarSignAdded == false) { priceTextEditingController.value=TextEditingValue( text: "\$" +priceTextEditingController.text); dollarSignAdded = true; } else if (value.isEmpty) { dollarSignAdded = false; } }"
        【解决方案8】:

        如果您使用StatefulWidget_controller 作为成员,则不会出现此问题。听起来很奇怪,但从无状态到有状态的转换效果很好(这是因为小部件在每个输入上都被重绘到不保留状态的文本编辑控制器)例如:

        有状态:(工作)

        class MyWidget extends StatefulWidget {
          const MyWidget(
              {Key? key})
              : super(key: key);
        
          @override
          _MyWidgetState createState() =>
              _MyWidgetState();
        }
        
        class _MyWidgetState
            extends State<MyWidget> {
          late TextEditingController _controller;
        
          @override
          void initState() {
            super.initState();
        
            _controller = TextEditingController(text: "My Text");
          }
        
          @override
          Widget build(BuildContext context) {
            return Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                TextField(
                  controller: _controller,
                ),
              ],
            );
          }
        }
        

        无状态:(问题)

        class MyWidget extends StatelessWidget {
          const MyWidget(
              {Key? key})
              : super(key: key);
        
          @override
          Widget build(BuildContext context) {
            return Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                TextField(
                  controller: TextEditingController(text: "My Text"),
                ),
              ],
            );
          }
        }
        

        【讨论】:

          【解决方案9】:

          这是一个完整示例,其中父小部件控制子小部件。父小部件使用计数器更新子小部件(TextTextField)。

          要更新 Text 小部件,您只需传入 String 参数即可。 要更新 TextField 小部件,您需要传入一个控制器,并在控制器中设置文本。

          main.dart:

          import 'package:flutter/material.dart';
          
          void main() => runApp(MyApp());
          
          class MyApp extends StatelessWidget {
            @override
            Widget build(BuildContext context) {
              return MaterialApp(
                title: 'Demo',
                home: Home(),
              );
            }
          }
          
          class Home extends StatelessWidget {
            @override
            Widget build(BuildContext context) {
              return Scaffold(
                  appBar: AppBar(
                    title: Text('Update Text and TextField demo'),
                  ),
                  body: ParentWidget());
            }
          }
          
          class ParentWidget extends StatefulWidget {
            @override
            _ParentWidgetState createState() => _ParentWidgetState();
          }
          
          class _ParentWidgetState extends State<ParentWidget> {
            int _counter = 0;
            String _text = 'no taps yet';
            var _controller = TextEditingController(text: 'initial value');
          
            void _handleTap() {
              setState(() {
                _counter = _counter + 1;
                _text = 'number of taps: ' + _counter.toString();
                _controller.text  = 'number of taps: ' + _counter.toString();
              });
            }
          
            @override
            Widget build(BuildContext context) {
              return Container(
                child: Column(children: <Widget>[
                  RaisedButton(
                    onPressed: _handleTap,
                    child: const Text('Tap me', style: TextStyle(fontSize: 20)),
                  ),
                  Text('$_text'),
                  TextField(controller: _controller,),
                ]),
              );
            }
          }
          

          【讨论】:

            【解决方案10】:

            只需更改控制器的text or value 属性。 如果您不编辑选择属性,则光标会转到新文本的第一个。

            onPress: () {
                     _controller.value=TextEditingValue(text: "sample text",selection: TextSelection.fromPosition(TextPosition(offset: sellPriceController.text.length)));                 
                         }
            

            或者如果您更改 .text 属性:

             onPress: () {
                     _controller.text="sample text";
                     _controller.selection = TextSelection.fromPosition(TextPosition(offset:_controller.text.length));          
                          }
            

            在对您无关紧要的情况下,不要更改选择属性

            【讨论】:

              【解决方案11】:
              1. 声明 TextEditingController。

              2. 为 TextField 提供控制器。

              3. 用户控制器的 text 属性来改变 textField 的值。

              关注这位官方solution to the problem

              【讨论】:

              • 这对之前添加的解决方案有什么好处?
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-05-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-12-15
              相关资源
              最近更新 更多