如何在Flutter的TextField中添加掩码?

13

我试图将日期掩码添加到textField中,因为我不喜欢Date Picker,例如对于出生日期,它没有那么灵活。之后,我相信我可以将字符串转换为datetime,然后继续项目,谢谢。

static final TextEditingController _birthDate = new TextEditingController();
    new TextFormField( 
            controller: _birthDate, 
            maxLength: 10,
            keyboardType: TextInputType.datetime, 
            validator: _validateDate
        ), String _validateDate(String value) { 
    if(value.isEmpty)
        return null;
    if(value.length != 10)
        return 'Enter date in DD / MM / YYYY format';
    return null; 
}

1
你有尝试过吗?有任何代码吗? - Saeed
static final TextEditingController _birthDate = new TextEditingController(); new TextFormField( controller: _birthDate, maxLength: 10, keyboardType: TextInputType.datetime, validator: _validateDate, ),String _validateDate(String value){ if(value.isEmpty) return null; if(value.length != 10) return '请以 DD / MM / YYYY 格式输入日期'; return null; }然而,用户需要使用 \。是否有一种方法可以自动禁用键盘选项? - Victor Henrique
尝试使用我的答案 @victor Henrique - siva kumar
6个回答

10

我修改了一些内容并成功地得到了预期结果。

我创建了这个类来定义变量。

static final _UsNumberTextInputFormatter _birthDate = new _UsNumberTextInputFormatter();

class _UsNumberTextInputFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(
TextEditingValue oldValue,
TextEditingValue newValue  ) {
final int newTextLength = newValue.text.length;
int selectionIndex = newValue.selection.end;
int usedSubstringIndex = 0;
final StringBuffer newText = new StringBuffer();
if (newTextLength >= 3) {
  newText.write(newValue.text.substring(0, usedSubstringIndex = 2) + '/');
  if (newValue.selection.end >= 2)
    selectionIndex ++;
}
if (newTextLength >= 5) {
  newText.write(newValue.text.substring(2, usedSubstringIndex = 4) + '/');
  if (newValue.selection.end >= 4)
    selectionIndex++;
}
if (newTextLength >= 9) {
  newText.write(newValue.text.substring(4, usedSubstringIndex = 8));
  if (newValue.selection.end >= 8)
    selectionIndex++;
}
// Dump the rest.
if (newTextLength >= usedSubstringIndex)
  newText.write(newValue.text.substring(usedSubstringIndex));
return new TextEditingValue(
  text: newText.toString(),
  selection: new TextSelection.collapsed(offset: selectionIndex),
); 
} 
}

最后,我给文本框添加了一个输入格式。
new TextFormField( 
          maxLength: 10,
          keyboardType: TextInputType.datetime, 
          validator: _validateDate,
          decoration: const InputDecoration(
            hintText: 'Digite sua data de nascimento',
            labelText: 'Data de Nascimento',
          ),
          inputFormatters: <TextInputFormatter> [
                WhitelistingTextInputFormatter.digitsOnly,
                // Fit the validating format.
                _birthDate,
              ]
        ),

现在没问题了,谢谢。

8

https://pub.dartlang.org/packages/masked_text

masked_text

这是一个用于掩码文本的软件包,如果您需要电话、邮编或任何类型的掩码,请使用它:D

入门指南

非常简单,它就像其他小部件一样。

new MaskedTextField
(
    maskedTextFieldController: _textCPFController,
    mask: "xx/xx/xxxx",
    maxLength: 10,
    keyboardType: TextInputType.number,
    inputDecoration: new InputDecoration(
    hintText: "Type your birthdate", labelText: "Date"),
);

'x'是您的文本通常会出现的字符。

此示例最终会生成类似于此内容:11/02/1995


它只是进入了无限循环,那个库不幸地没有工作。 - Hardy
8
不要使用这个。以下是更好的方法,使用本地的TextField小部件:https://pub.dev/packages/mask_text_input_formatter - Renan Coelho
@RenanCoelho 你之后会手动更新文本并保持格式吗? - TootsieRockNRoll

2

你可以使用Flutter包mask_text_input_formatter(已获得超过850个赞)

使用方法如下:

import 'package:mask_text_input_formatter/mask_text_input_formatter.dart';

var maskFormatter = new MaskTextInputFormatter(
  mask: '+# (###) ###-##-##', 
  filter: { "#": RegExp(r'[0-9]') },
  type: MaskAutoCompletionType.lazy
);

// In your build method
TextField(inputFormatters: [maskFormatter])

1
我的解决方案:
class MaskTextInputFormatter extends TextInputFormatter {
  final int maskLength;
  final Map<String, List<int>> separatorBoundries;

  MaskTextInputFormatter({
    String mask = "xx.xx.xx-xxx.xx",
    List<String> separators = const [".", "-"],
  })  : this.separatorBoundries = {
          for (var v in separators)
            v: mask.split("").asMap().entries.where((entry) => entry.value == v).map((e) => e.key).toList()
        },
        this.maskLength = mask.length;

  @override
  TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
    final int newTextLength = newValue.text.length;
    final int oldTextLength = oldValue.text.length;
    // removed char
    if (newTextLength < oldTextLength) return newValue;
    // maximum amount of chars
    if (oldTextLength == maskLength) return oldValue;

    // masking
    final StringBuffer newText = StringBuffer();
    int selectionIndex = newValue.selection.end;

    // extra boundaries check
    final separatorEntry1 = separatorBoundries.entries.firstWhereOrNull((entry) => entry.value.contains(oldTextLength));
    if (separatorEntry1 != null) {
      newText.write(oldValue.text + separatorEntry1.key);
      selectionIndex++;
    } else {
      newText.write(oldValue.text);
    }
    // write the char
    newText.write(newValue.text[newValue.text.length - 1]);

    return TextEditingValue(
      text: newText.toString(),
      selection: TextSelection.collapsed(offset: selectionIndex),
    );
  }
}

0

这个解决方案检查日期是否超出范围(例如,没有像13这样的月份)。它非常低效,但它能够工作。


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

class DateFormatter extends TextInputFormatter {
  final String mask = 'xx-xx-xxxx';
  final String separator = '-';

  @override
  TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
 if(newValue.text.length > 0) {
  if(newValue.text.length > oldValue.text.length) {
    String lastEnteredChar = newValue.text.substring(newValue.text.length-1);
    if(!_isNumeric(lastEnteredChar)) return oldValue;

    if(newValue.text.length > mask.length) return oldValue;
    if(newValue.text.length < mask.length && mask[newValue.text.length - 1] == separator) {

      String value = _validateValue(oldValue.text);
      print(value);

      return TextEditingValue(
        text: '$value$separator$lastEnteredChar',
        selection: TextSelection.collapsed(
          offset: newValue.selection.end + 1,
        ),
      );
    }

    if(newValue.text.length == mask.length) {
      return TextEditingValue(
        text: '${_validateValue(newValue.text)}',
        selection: TextSelection.collapsed(
          offset: newValue.selection.end,
        ),
      );
    }
  }
}
return newValue;
}

bool _isNumeric(String s) {
if(s == null) return false;
return double.parse(s, (e) => null) != null;
}

 String _validateValue(String s) {
String result = s;

if (s.length < 4) { // days
  int num = int.parse(s.substring(s.length-2));
  String raw = s.substring(0, s.length-2);
  if (num == 0) {
    result = raw + '01';
  } else if (num > 31) {
    result = raw + '31';
  } else {
    result = s;
  }
} else if (s.length < 7) { // month
  int num = int.parse(s.substring(s.length-2));
  String raw  = s.substring(0, s.length-2);
  if (num == 0) {
    result = raw + '01';
  } else if (num > 12) {
    result = raw + '12';
  } else {
    result = s;
  }
} else { // year
  int num = int.parse(s.substring(s.length-4));
  String raw  = s.substring(0, s.length-4);
  if (num < 1950) {
    result = raw + '1950';
  } else if (num > 2006) {
    result = raw + '2006';
  } else {
    result = s;
  }
}

print(result);
return result;
}

}

-2
现在您可以使用TextField的布尔属性"obscureText"来掩盖输入。

2
与问题无关。提问者想要掩盖输入,而不是用*或其他字符隐藏它。 - jRicardo

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