状态更改后 TextFormField 正在丢失值

TextFromField is losing value after sate changed

TextFromField 在状态更改时丢失其值。

这是完整的代码https://github.com/imSaharukh/cgpa_final.git

我该如何解决?

Check this GIF

问题在于您如何创建 TextEditingControllers。每次调用构建方法时,都会创建新的 TextEditingControllers。

您要做的是在 _MyHomePageState class 的顶部创建 3 个 TextEditingController 变量。 (也不需要在飞镖中使用 new 关键字)。

class _MyHomePageState extends State<MyHomePage> {
  final _formKey = GlobalKey<FormState>();
  TextEditingController nameController = TextEditingController();
  TextEditingController cgpaController = TextEditingController();
  TextEditingController crController = TextEditingController();

并将这些传递给您的 CustomCard

child: CustomCard(
    key: UniqueKey(),
    index: index,
    cgpa: cgpa,
    namecontroller: nameController,
    cgpacontroller: cgpaController,
    crcontroller: crController),

希望对您有所帮助

编辑:

我不知道如何创建拉取请求,但我为您做了一些更改并在 iOS sim 上对其进行了测试。

我做了什么:

  • 将详细信息重命名为课程
  • 将 CusomCard 转换为有状态小部件
  • 现在只有一个 Course 对象被传递给 CustomCard
  • 现在可以根据课程获得钥匙。
  • 将控制器移至 CustomCard
  • 修改了 CGPA 中的一些代码以使其全部正常工作
class _MyHomePageState extends State<MyHomePage> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Stack(
          children: [
            Column(
              children: [
                Expanded(
                  child: Consumer<CGPA>(builder: (context, cgpa, _) {
                    return Form(
                      key: _formKey,
                      child: ListView.builder(
                        scrollDirection: Axis.vertical,
                        shrinkWrap: true,
                        itemCount: cgpa.courses.length,
                        itemBuilder: (BuildContext context, int index) {
                          return Dismissible(
                            key: Key(cgpa.getKeyValue(index)),
                            onDismissed: (direction) {
                              cgpa.remove(index);
                              print(cgpa.courses.length);
                            },
                            child: CustomCard(
                              course: cgpa.getCourse(index),
                            ),
                          );
                        },
                      ),
                    );
                  }),
                ),
              ],
            ),
            Align(
              alignment: Alignment.bottomRight,
              child: Padding(
                padding: const EdgeInsets.all(15.0),
                child: FloatingActionButton(
                  child: Icon(Icons.add),
                  onPressed: () {
                    Provider.of<CGPA>(context, listen: false).add();
                    // print(cgpa.details.length);
                    //  cgpa.details[indexs] = Details();
                  },
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: OutlineButton(
        onPressed: () {
          // for (var item in cgpa.details) {
          //   print(item.credit);
          // }
        },
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 30),
          child: Text("calculate"),
        ),
        shape: new RoundedRectangleBorder(
          borderRadius: new BorderRadius.circular(30.0),
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
    );
  }
}

自定义卡片


class CustomCard extends StatefulWidget {
  CustomCard({@required this.course});

  final Course course;

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

class _CustomCardState extends State<CustomCard> {
  TextEditingController nameController;
  TextEditingController cgpaController;
  TextEditingController crController;

  @override
  void initState() {
    super.initState();
    nameController = TextEditingController(text: widget.course.name);
    cgpaController = TextEditingController(
        text: widget.course.gpa == null ? "" : widget.course.gpa.toString());
    crController = TextEditingController(
        text: widget.course.credit == null
            ? ""
            : widget.course.credit.toString());
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Row(
          children: [
            Expanded(
              flex: 3,
              child: TextFormField(
                controller: nameController,
                decoration: InputDecoration(labelText: "COURSE NAME"),
                onChanged: (value) {
                  widget.course.name = value;
                },
              ),
            ),
            SizedBox(
              width: 10,
            ),
            Expanded(
              child: TextFormField(
                controller: cgpaController,
                keyboardType: TextInputType.number,
                decoration: InputDecoration(labelText: "GPA"),
                onChanged: (value) {
                  //print(value);
                  widget.course.gpa = double.parse(value);
                },
                validator: (value) {
                  if (double.parse(value) > 4 && double.parse(value) < 0) {
                    return 'can\'t more then 4';
                  }
                  return null;
                },
              ),
            ),
            SizedBox(
              width: 10,
            ),
            Expanded(
              child: TextFormField(
                controller: crController,
                keyboardType: TextInputType.number,
                decoration: InputDecoration(labelText: "CREDIT"),
                onChanged: (value) {
                  widget.course.credit = double.parse(value);
                },
                validator: (value) {
                  if (value.isEmpty) {
                    return 'can\'t be empty';
                  }
                  return null;
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

CGPA

class CGPA with ChangeNotifier {
  Map<int, Course> courses = new Map();

  var index = 0;

  add() {
    courses[index] = Course();
    index++;
    notifyListeners();
  }

  remove(int listIndex) {
    courses.remove(courses.keys.toList()[listIndex]);
    notifyListeners();
  }

  String getKeyValue(int listIndex) => courses.keys.toList()[listIndex].toString();

  Course getCourse(int listIndex) => courses.values.toList()[listIndex];
}

class Course {
  Course({this.credit, this.gpa, this.name});

  String name;
  double credit;
  double gpa;

  @override
  String toString() {
    return 'Course{name: $name, credit: $credit, gpa: $gpa}';
  }
}