首页 > 解决方案 > 使用 Consumer 的 TextField 问题,在键盘上点击“完成”会导致 textField 被清除

问题描述

编辑:试图删除帖子,但因为答案而无法删除。因此,我正在编辑整篇文章以更好地描述我遇到的新问题,因为我现在已经缩小了问题范围。

我看过其他在不同情况下解决此问题的帖子,但我无法用他们的解决方案解决我的情况。

我有一个下拉菜单,用于快速访问经常输入的销售人员,该菜单接受任何新的销售人员姓名并添加到列表中。这与我的屏幕有关,我无法弄清楚如何不让键盘清除点击“完成”的文本字段。

任何帮助表示赞赏!

屏幕:

class SmallAddSaleScreen extends StatefulWidget {
  @override
  _SmallAddSaleScreenState createState() => _SmallAddSaleScreenState();
}

class _SmallAddSaleScreenState extends State<SmallAddSaleScreen> {
  final randomGen = Faker.withGenerator(random);
  final uuid = Uuid();
  final salesPerson = TextEditingController();
  final saleAmount = TextEditingController();
  final item = TextEditingController();
  final dateEdited = DateTime.now().millisecondsSinceEpoch;
  int saleDate = DateTime.now().millisecondsSinceEpoch;

  String capitolizeFirst(String string) => string[0].toUpperCase() + string.substring(1);

  @override
  void initState() {
    item.text = capitolizeFirst(randomGen.lorem.word());
    saleAmount.text = (random.integer(13000) + random.decimal()).toStringAsFixed(2);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    String formattedDate = DateFormat.yMMMMd().format(DateTime.fromMillisecondsSinceEpoch(saleDate));

    Future<void> selectSaleDate(BuildContext context) async {
      final DateTime? picked = await showDatePicker(
        context: context,
        initialDate: DateTime.fromMillisecondsSinceEpoch(saleDate),
        firstDate: DateTime(2015, 8),
        lastDate: DateTime(2101),
      );
      if (picked != null)
        setState(() {
          saleDate = picked.millisecondsSinceEpoch;
        });
    }

    return Scaffold(
      body: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Column(
            children: [
              SizedBox(height: 20),
              Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Text('Sales Person:'),
                    SizedBox(width: 20),
                    Container(
                      width: 350,
                      child: Consumer(builder: (context, watch, child) {
                        salesPerson.text = watch(appState).selectedSaleSource!;
                        return TextField(
                          controller: salesPerson,
                          keyboardType: TextInputType.text,
                          textCapitalization: TextCapitalization.words,
                          autocorrect: false,
                          decoration: InputDecoration(
                            border: OutlineInputBorder(borderSide: BorderSide(color: Colors.black)),
                            labelText: 'Name',
                          ),
                        );
                      }),
                    ),
                  ]),
              SizedBox(height: 20),
              Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Text('Sale Amount:'),
                    SizedBox(width: 20),
                    Container(
                      width: 350,
                      child: TextField(
                        controller: saleAmount,
                        keyboardType: TextInputType.numberWithOptions(decimal: true),
                        textCapitalization: TextCapitalization.words,
                        autocorrect: false,
                        decoration: InputDecoration(
                          border: OutlineInputBorder(borderSide: BorderSide(color: Colors.black)),
                          labelText: '\$',
                        ),
                      ),
                    ),
                  ]),
              SizedBox(height: 20),
              Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Text('Item:'),
                    SizedBox(width: 75),
                    Container(
                      width: 350,
                      child: TextField(
                        controller: item,
                        keyboardType: TextInputType.text,
                        textCapitalization: TextCapitalization.words,
                        autocorrect: false,
                        decoration: InputDecoration(
                          border: OutlineInputBorder(borderSide: BorderSide(color: Colors.black)),
                          labelText: 'Item',
                        ),
                      ),
                    ),
                  ]),
              SizedBox(height: 20),
              Container(
                height: 50,
                child: Row(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Text('Sale date: '),
                      SizedBox(width: 40),
                      Container(
                        width: 350,
                        child: Text(formattedDate),
                      ),
                    ]),
              ),
            ],
          ),
          SizedBox(width: 50),
          Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              SizedBox(height: 40),
              Container(
                width: 250,
                child: SalesSourcePulldownMenuWidget(),
              ),
              SizedBox(height: 100),
              Container(
                width: 250,
                child: TextButton(
                    style: ButtonStyle(
                        textStyle: MaterialStateProperty.all(TextStyle(fontWeight: FontWeight.bold)),
                        foregroundColor: MaterialStateProperty.all(Colors.white),
                        backgroundColor: MaterialStateProperty.all(Colors.amber[800])),
                    onPressed: () async {
                      await selectSaleDate(context);
                    },
                    child: const Text('SELECT SALE DATE')),
              ),
              SizedBox(height: 20),
              Container(
                width: 250,
                child: TextButton(
                  style: ButtonStyle(
                      textStyle: MaterialStateProperty.all(TextStyle(fontWeight: FontWeight.bold)),
                      foregroundColor: MaterialStateProperty.all(Colors.white),
                      backgroundColor: MaterialStateProperty.all(Colors.amber[800])),
                  child: const Text('SAVE'),
                  onPressed: () async {
                    if (salesPerson.text.isNotEmpty && saleAmount.text.isNotEmpty && item.text.isNotEmpty) {
                      final userID = context.read(appState).authorizedLocalUser!.localID;
                      final sale = Sale(
                        salesPerson: salesPerson.text.trim(),
                        saleAmount: double.parse(saleAmount.text.trim()),
                        item: item.text.trim(),
                        saleDate: saleDate,
                        dateModified: dateEdited,
                        createdBy: userID,
                        saleUUID: uuid.v4(),
                      );
                      await context.read(cudServices).createSaleData(context, sale);
                      await context.read(appState).addSaleSource(salesPerson.text.trim());
                      context.read(appState).setSaleSource('');
                      salesPerson.text;
                      context.read(appState).saveSuccess(context);
                    } else {
                      context.read(appState).emptyField(context);
                    }
                    item.text = capitolizeFirst(randomGen.lorem.word()); // Randomize input
                    saleAmount.text =
                        (random.integer(13000) + random.decimal()).toStringAsFixed(2); // Randomize input
                    setState(() {
                      saleDate = DateTime.now().millisecondsSinceEpoch; // Reset input
                    });
                  },
                ),
              )
            ],
          )
        ],
      ),
    );
  }
}

下拉小部件:

class _SalesSourcePulldownMenuWidgetState extends State<SalesSourcePulldownMenuWidget> {
  late String? selectedSaleSource;
  bool selected = false;
  
  @override
  void initState() {
    context.read(appState).getSaleSources();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    late List<String> listItems;
    late List<DropdownMenuItem<String>> menuItems;

    return Consumer(builder: (context, watch, child) {
      listItems = watch(appState).saleSources;
      selectedSaleSource = watch(appState).selectedSaleSource;

      if (selectedSaleSource == '') {
        selected = false;
      }

      menuItems = listItems
          .map((String value) => DropdownMenuItem<String>(
                value: value,
                child: Text(value),
              ))
          .toList();
      return DropdownButton<String>(
        value: selected ? selectedSaleSource : null,
        isExpanded: true,
        hint: const Text('Existing persons'),
        items: menuItems,
        onTap: () {
          selected = true;
        },
        onChanged: (String? newValue) {
          setState(() {
            if (newValue != null) {
              context.read(appState).setSaleSource(newValue);
              selectedSaleSource = newValue;
            }
          });
        },
      );
    });
  }
}

标签: flutterdartstatedemo

解决方案


这是正常行为,在 initState() 方法中为这些变量赋值:

class _SmallAddSaleScreenState extends State<SmallAddSaleScreen> {
  final randomGen = Faker.withGenerator(random);
  final uuid = Uuid();
  final salesPerson = TextEditingController();
  final saleAmount = TextEditingController();
  final item = TextEditingController();
  final dateEdited = DateTime.now().millisecondsSinceEpoch;
  int saleDate = DateTime.now().millisecondsSinceEpoch;
  
  String capitolizeFirst(String _s) => _s[0].toUpperCase() + _s.substring(1);
  String formattedDate(DateTime _d) = DateFormat.yMMMMd().format(DateTime.fromMillisecondsSinceEpoch(_d));

  
  @override
  void initState() {
    item.text = capitolizeFirst(randomGen.lorem.word());       
    saleAmount.text = (random.integer(13000) + random.decimal()).toStringAsFixed(2); 
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Column(
...

推荐阅读