带有掩码文本输入格式化程序的TextFormField在更改值时清除内容

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

m building a form with several fields and I
正在使用控制器初始化它们的值。 有些字段是纯文本字段,但其他字段有掩码,例如电话和邮政编码字段。

一旦我将字段置于焦点上并开始退格以擦除最后一个字符,它就可以在没有遮罩的字段上正常工作。带掩码的字段会清除该字段的全部内容。

我正在使用 Flutter 3 和 mask_text_input_formatter ^2.4.0。

这是我用两个字段重现问题的代码。 如果运行此代码并将焦点放在名称字段上,您可以退格它,并且只有最后一个字符会被清除。 但在电话字段中,这会导致整个字段被清除。

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

final phoneMaskFormatter = MaskTextInputFormatter(mask: '(###) ### ####');

class Test extends StatefulWidget {
  const Test({Key? key}) : super(key: key);

  @override
  State<Test> createState() => _TestState();
}

class _TestState extends State<Test> {
  final _formKey = GlobalKey<FormState>();

  late TextEditingController _nameController;
  late TextEditingController _phoneController;

  var myData = {'name': 'William', 'phone': '(305) 786 1234'};

  @override
  void initState() {
    super.initState();
    _nameController = TextEditingController();
    _phoneController = TextEditingController();

    _nameController.text = myData['name']!;
    _phoneController.text = myData['phone']!;
  }

  @override
  void dispose() {
    super.dispose();
    _nameController.dispose();
    _phoneController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Form(
          key: _formKey,
          child: Container(
            padding: EdgeInsets.all(50),
            child: Column(
              children: [
                Text('Name: ${myData['name']}'),
                Text('Phone: ${myData['phone']}'),
                SizedBox(height: 100),
                TextFormField(
                    controller: _nameController,
                    onChanged: (value) {
                      // do my stuff
                      setState(() {
                        myData['name'] = value;
                      });
                    }),
                TextFormField(
                    controller: _phoneController,
                    inputFormatters: [phoneMaskFormatter],
                    onChanged: (value) {
                      // do my stuff
                      setState(() {
                        myData['phone'] = value;
                      });
                    }),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

现在唯一对我有用的就是摘掉电话区域的面具。

flutter controller textformfield
2个回答
0
投票

使用 extended_masked_text: ^2.3.1 满足您的要求。

_phoneController 的声明和初始化与您所做的相同。

MaskedTextController _phoneController =
      MaskedTextController(mask: '(000) 000 0000');

void initState() {
...
  _phoneController.text = myData['phone']!;
...
}

并删除

inputFormatters: [numberController]


0
投票

我找到了一个可能适合您的解决方案,因为我也遇到过同样的情况。只需将 MaskTextInputFormatter 替换为下一个 PhoneInputFormatter 即可。

class PhoneInputFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    // Only process when the user is entering text
    if (newValue.text.isNotEmpty) {
      // Remove all non-digit characters
      String newText = newValue.text.replaceAll(RegExp(r'\D'), '');

      // If the new text length is greater than 10 (including the area code), truncate it
      if (newText.length > 10) {
        newText = newText.substring(0, 10);
      }

      // Format the text according to the mask
      String formattedText = '';
      for (int i = 0; i < newText.length; i++) {
        if (i == 0) {
          formattedText += '(';
        } else if (i == 3) {
          formattedText += ') ';
        } else if (i == 6) {
          formattedText += '-';
        }
        formattedText += newText[i];
      }

      // Return the formatted text
      return newValue.copyWith(
        text: formattedText,
        selection: TextSelection.collapsed(offset: formattedText.length),
      );
    }

    // Return the unchanged value
    return newValue;
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.