点击其中一个 TextField 时,TextField 文本会被清除

问题描述 投票:0回答:4

我遇到了一些奇怪的问题,如果您点击其中一个文本字段,它总是会被清除。

class MyEditText extends StatefulWidget {
  static String tag = "MyEditText";
  @override
  MyEditTextState createState() => MyEditTextState();
}

class MyEditTextState extends State<MyEditText> {
  String results = "";
  final TextEditingController controller = new TextEditingController();
  final TextEditingController controller1 = new TextEditingController();

  @override
  Widget build(BuildContext context) {
    final email = TextField(
      decoration: InputDecoration(
          hintText: 'Enter Email',
          contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0)),
    );

    final password = TextField(
      obscureText: true,
      decoration: InputDecoration(
        hintText: 'Enter Password',
        contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
      ),
    );

    return new Scaffold(
      appBar: new AppBar(
        automaticallyImplyLeading: false,
        title: new Text("EditText Sample"),
        backgroundColor: Colors.yellow,
      ),
      body: new Container(
        child: new Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[email, password],
        ),
      ),
    );
  }
}

我正在为其使用静态小部件,并且此屏幕启动的所有类也是静态的。

注意:如果我注释掉所有 TextEditingController 及其用法,一切都会正常,所以我不明白 TextEditingController 有什么问题

flutter flutter-layout
4个回答
2
投票

感谢更新代码。

您的

TextEditingController
被清除的原因是因为您在
State<MyEditText>
内部声明了变量。当状态重新初始化时 - 这些变量也会重新初始化。

我可以看到两种方法来解决这个问题:

#1 - 将控制器从 State 移出到父类,将它们作为参数传递

控制器在

MyEditText
小部件之外声明和维护 - 在父类中。

class MyEditText extends StatefulWidget {
  MyEditText({ Key key, this.emailController, this.passwordController }): super(key: key);

  final TextEditingController emailController;
  final TextEditingController passwordController;

  static String tag = "MyEditText";

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

class MyEditTextState extends State<MyEditText> {
  String results = "";

  @override
  Widget build(BuildContext context) {
    // ...
    TextField(
      controller: widget.emailController,
      // ...,
    ),
    TextField(
      controller: widget.passwordController,
      // ...,
    ),
    // ...
  }
}

然后在父类中声明控制器并将它们作为参数传递给

MyEditText
:

final emailController = TextEditingController();
final passwordController = TextEditingController();
// ...
MyEditText(
  emailController: emailController,
  passwordController: passwordController,
)

#2 - 在
didUpdateWidget
调用

时重用旧状态的控制器

控制器可以在

MyEditText
类之外声明,但如果不是 - 小部件会自行创建并维护
TextEditingController

class MyEditText extends StatefulWidget {
  MyEditText({ Key key, this.emailController, this.passwordController }): super(key: key);

  final TextEditingController emailController;
  final TextEditingController passwordController;

  static String tag = "MyEditText";

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

class MyEditTextState extends State<MyEditText> {

  TextEditingController _emailController;
  TextEditingController _passwordController;

  @override
  void initState() {
    super.initState();
    if (widget.emailController == null)
      _emailController = TextEditingController();
    if (widget.passwordController == null)
      _passwordController = TextEditingController();
  }

  @override
  void didUpdateWidget(MyEditText oldWidget) {
    super.didUpdateWidget(oldWidget);

    if (widget.emailController == null && oldWidget.emailController != null)
      _emailController = TextEditingController.fromValue(oldWidget.emailController.value);
    else if (widget.emailController != null && oldWidget.emailController == null)
      _emailController = null;

    if (widget.passwordController == null && oldWidget.passwordController != null)
      _passwordController = TextEditingController.fromValue(oldWidget.passwordController.value);
    else if (widget.passwordController != null && oldWidget.passwordController == null)
      _passwordController = null;
  }

  @override
  Widget build(BuildContext context) {
    // ...
    TextField(
      controller: _emailController ?? widget.emailController,
      // ...,
    ),
    TextField(
      controller: _passwordController ?? widget.passwordController,
      // ...,
    ),
    // ...
  }
  // ...
}

两种方法都很相似,只是第二种方法自行调节

State<MyEditText>
变量。

我将让您决定哪一个更适合您的情况。

让我知道这是否有帮助。


0
投票

 

   TextEditingController controller = TextEditingController();
    TextEditingController controller1 = TextEditingController();

    final email = TextField(
      controller: emailController,
      keyboardType: TextInputType.emailAddress,
      decoration: InputDecoration(
          prefixIcon: Icon(Icons.person_outline, color: Colors.grey),
          hintText: 'Enter Email',
          contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0)),
    );

    final password = TextField(
      controller1: passwordController,
      obscureText: true,
      decoration: InputDecoration(
        prefixIcon: Icon(Icons.lock_open, color: Colors.grey),
        hintText: 'Enter Password',
        contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
      ),
    );

     clearName() {
        controller.text = '';
        controller1.text = '';
     }
 
 //call the clearName function wherever needed


0
投票

你可以试试这个方法吗

TextFormField(
                cursorColor: Colors.white,
                autofocus: false,
                keyboardType:
                TextInputType.emailAddress,
                controller: _textEditingControllerEmail,
                ),

 TextFormField(
               autofocus: false,
               controller:_textEditingControllerPassword,
               cursorColor: Colors.white,
               obscureText: true,
               ),

0
投票

只需重写 didUpdateWidget() 即可,如下所示。仅当您停留在同一屏幕上时此功能才有效。移动到不同的屏幕将重新初始化所有内容。

class MyEditText extends StatefulWidget {
  static String tag = "MyEditText";
  // Move the controllers to the widget.
  final TextEditingController controller = new TextEditingController();
  final TextEditingController controller1 = new TextEditingController();

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

class MyEditTextState extends State<MyEditText> {
  String results = "";
  
  @override
  void didUpdateWidget(oldWidget) // Override it and copy the old ones over if not null
  {
    super.didUpdateWidget(oldWidget);
    if((widget.controller != null) && (oldWidget.controller != null))
       widget.controller.text = oldWidget.controller.text;
    if((widget.controller1 != null) && (oldWidget.controller1 != null))
       widget.controller1.text = oldWidget.controller1.text;
    
  }
  ... //The rest of your code
© www.soinside.com 2019 - 2024. All rights reserved.