Flutter中TextField在TextInputType更改后重置控制器

15

我在我的应用程序中使用全屏对话框,以便用户将值输入到文本字段中。其中一些值是字符串,一些是整数。因此,我希望相应更改键盘,以使不必要的键消失。这是我的实现:

import 'package:flutter/material.dart';
import 'package:meal_tracker/model/food_model.dart';

class AddFoodDialog extends StatelessWidget {
  TextEditingController nameController = TextEditingController(),
      carbsController = TextEditingController(),
      fatController = TextEditingController(),
      proteinController = TextEditingController(),
      amountController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Add Food"),
        actions: <Widget>[
          FlatButton(
            child: Text(
              "SAVE",
              style: TextStyle(color: Colors.white),
            ),
            onPressed: () {
              _handleSave(context);
            },
          )
        ],
      ),
      body: Form(
          child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: <Widget>[
            TextFormField(
              decoration: InputDecoration(labelText: "Name"),
              controller: nameController,
            ),
            TextFormField(
              decoration: InputDecoration(labelText: "Carbs per 100g"),
              controller: carbsController,
              keyboardType: TextInputType.number,
            ),
            TextFormField(
              decoration: InputDecoration(labelText: "Fat per 100g"),
              controller: fatController,
              keyboardType: TextInputType.number,
            ),
            TextFormField(
              decoration: InputDecoration(labelText: "Protein per 100g"),
              controller: proteinController,
              keyboardType: TextInputType.number,
            ),
            TextFormField(
              decoration: InputDecoration(labelText: "Amount in g"),
              controller: amountController,
              keyboardType: TextInputType.number,
            ),
          ],
        ),
      )),
    );
  }

  void _handleSave(BuildContext context) {
    print("Dialog text: " + nameController.text);
    Navigator.of(context).pop(Food(
        name: nameController.text,
        carbsPer100g: double.parse(carbsController.text),
        fatPer100g: double.parse(fatController.text),
        proteinPer100g: double.parse(proteinController.text),
        amount: double.parse(amountController.text)));
  }
}

问题在于当我在“名称”文本框中输入一些内容,该文本框具有 TextInputType.text ,然后点击另一个具有TextInputType.number的文本框时,“名称”字段出现了不明原因的清空。这种情况也会反向发生。


5
你需要创建一个StatefulWidget,并将控制器放在State中。在StatelessWidget中添加可变字段是行不通的。 - Jonah Williams
你有没有避免大量TextEditingControllers的方法? - Chingiz
3个回答

19

我必须将TextEditingControllers放入一个Stateful Widget中,这最终起作用了。感谢Jonah Williams的快速回复!


4
你们拯救了我的一天。谢谢你们。 - Jithin Jude

7

在你的情况下,你需要声明一个StatefulWidget。如果控制器在build函数内部定义,也可能会导致类似的问题。


6

TextFields的值重置可能有两个主要原因:

  • 无状态小部件
  • 将TextEditingController属性声明为final

如果您想处理任何小部件的状态,特别是在对话框(SimpleDialog)内部,请始终创建一个单独的StatefulWidget类和TextEditingController属性作为变量var

下面是完整的StatefulWidget示例,它不会在切换时重置TextFields值:

class ReportDialog extends StatefulWidget {
  @override
  _ReportDialogState createState() => new _ReportDialogState();
}

class _ReportDialogState extends State<ReportDialog> {
  var selectedConfiguration = SharedConfiguration().selectedConfiguration;
  var titleTextField = TextEditingController();
  var descriptionTextField = TextEditingController();

  @override
  Widget build(BuildContext context) {
    final reportButton = ReusableWidgets.getButton('REPORT',
        Colors.redAccent, Colors.white, reportButtonAction, context, 46);

    return SimpleDialog(
      contentPadding: EdgeInsets.fromLTRB(20, 10, 20, 10),
      children: <Widget>[
        new TextField(
          controller: titleTextField,
          decoration: new InputDecoration(
            border: new OutlineInputBorder(),
            hintText: 'Title',
          ),
          maxLines: 1,
        ),
        SizedBox(height: 8.0),
        new TextField(
          controller: descriptionTextField,
          decoration: new InputDecoration(
            border: new OutlineInputBorder(),
            hintText: 'Add your message here...',
            helperText: 'Keep it short, this is just a demo.',
          ),
          maxLines: 6,
        ),
        SizedBox(height: 20.0),
        reportButton
      ],
    );
  }

  void reportButtonAction() {
    Navigator.of(context).pop();
  }
}

希望这对您有所帮助 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接