如何在状态更改时保持新的TextFormField值?

时间:2019-12-15 12:17:06

标签: flutter

我想创建很多带有int值的TextFormField。如果用户将TextFormField值更改为i,则将FAB设置为visible。因此,如果用户单击FAB,则可以保存新值。但是Setstate存在问题。当用户更改TextFormField时设置其触发器OnChanged的值,并在setstate内将FAB设置为可见。使用setState时,将其TextFormFields重置为初始值。如何避免此问题?

谢谢

这是我的示例代码

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
bool FabVisible = false;
final List<TextEditingController> controllers = List.generate(6, (index) {
  return TextEditingController();
});

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        child: Scaffold(
          floatingActionButton: FAB(),
          body: Center(
            child: MyWidget(),
          ),
        ),
      ),
    );
  }

  FloatingActionButton FAB() {
    return FabVisible
        ? FloatingActionButton(onPressed: () {}, child: Icon(Icons.save))
        : null;
  }
}

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
//  final TextEditingController controller = TextEditingController();
//  final TextEditingController controller2 = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        SingleChildScrollView(
          child: Column(
            children: textFields(),
          ),
        ),
      ],
    );
  }

  List<TextFormField> textFields() {
    List<TextFormField> trash = List();

    for (int i = 0; i <= 5; i++) {
      TextEditingController controller = controllers[i];
      controller.value = TextEditingValue(
          text: 10.toString(),
          selection: TextSelection.fromPosition(
              TextPosition(offset: (10.toString()).length)));

      trash.add(
        TextFormField(
          onChanged: (txt) {
            controller.value = TextEditingValue(
                text: txt,
                selection: TextSelection.fromPosition(
                  TextPosition(offset: txt.length),
                ));
            setState(() {
              FabVisible = true;
            });
          },
          keyboardType: TextInputType.number,
          inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
          controller: controller,
          style: TextStyle(color: Colors.white),
          textAlign: TextAlign.center,
          decoration: InputDecoration.collapsed(
            hintText: "",
            fillColor: Colors.teal,
            focusColor: Colors.yellow,
          ),
        ),
      );
    }
    return trash;
  }
}

1 个答案:

答案 0 :(得分:0)

调用setState()时,它将重建小部件,因此再次调用textFields()函数。为避免这种情况,我建议利用initState()initState()仅在屏幕首次加载时被调用。

让我们看看如何使用它:

class _MyWidgetState extends State<MyWidget> {
//  final TextEditingController controller = TextEditingController();
//  final TextEditingController controller2 = TextEditingController();
  final List<Widget> children = [];

  @override
  void initState() {
    textFields();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        SingleChildScrollView(
          child: Column(
            children: children,
          ),
        ),
      ],
    );
  }

  void textFields() {
    for (int i = 0; i <= 5; i++) {
      TextEditingController controller = controllers[i];
      controller.value = TextEditingValue(
          text: "10", // same thing as 10.toString()
          selection: TextSelection.fromPosition(
              TextPosition(offset: ("10").length)));

      children.add(
        TextFormField(
          onChanged: (txt) {
            controller.value = TextEditingValue(
                text: txt,
                selection: TextSelection.fromPosition(
                  TextPosition(offset: txt.length),
                ));
            setState(() {
              FabVisible = true;
            });
          },
          keyboardType: TextInputType.number,
          inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
          controller: controller,
          style: TextStyle(color: Colors.white),
          textAlign: TextAlign.center,
          decoration: InputDecoration.collapsed(
            hintText: "",
            fillColor: Colors.teal,
            focusColor: Colors.yellow,
          ),
        ),
      );
    }
  }
}