我正在寻找一个用于文本字段的 inputformatter 示例,它将是日期 mm/dd/yyyy,当用户键入更新格式时,我正在尝试执行的操作。例如用户开始输入mm并输入/,然后当输入dd时输入/。
有没有人做过这个或者有一个例子?我已经用其他语言完成了,但在 flutter/dart 中找不到类似的方法。
这是我迄今为止尝试过的,但无法使逻辑正确。有任何想法吗?
class _DateFormatter 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 == 2) {
newText.write(newValue.text.substring(0, 2) + '/ ');
if (newValue.selection.end == 3)
selectionIndex+=3;
}
if (newTextLength == 5) {
newText.write(newValue.text.substring(0, 5) + '/ ');
if (newValue.selection.end == 6)
selectionIndex += 6;
}
// Dump the rest.
if (newTextLength >= usedSubstringIndex)
newText.write(newValue.text.substring(usedSubstringIndex));
return new TextEditingValue(
text: newText.toString(),
selection: new TextSelection.collapsed(offset: selectionIndex),
);
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢
Ari*_*911 11
这是基于 Jochem Toolenaar 答案的改进版本。此版本会自动为您删除正斜杠并将用户限制为 8 位数字。
class DateTextFormatter extends TextInputFormatter {
static const _maxChars = 8;
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
var text = _format(newValue.text, '/');
return newValue.copyWith(text: text, selection: updateCursorPosition(text));
}
String _format(String value, String seperator) {
value = value.replaceAll(seperator, '');
var newString = '';
for (int i = 0; i < min(value.length, _maxChars); i++) {
newString += value[i];
if ((i == 1 || i == 3) && i != value.length - 1) {
newString += seperator;
}
}
return newString;
}
TextSelection updateCursorPosition(String text) {
return TextSelection.fromPosition(TextPosition(offset: text.length));
}
}
Run Code Online (Sandbox Code Playgroud)
我也为此苦苦挣扎。我最终得到了以下不太优雅的解决方案:
class DateInputTextField extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _DateInputTextFieldState();
}
}
class _DateInputTextFieldState extends State<DateInputTextField> {
@override
Widget build(BuildContext context) {
return TextField(
keyboardType: TextInputType.number,
inputFormatters: [DateTextFormatter()],
onChanged: (String value) {},
);
}
}
class DateTextFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
//this fixes backspace bug
if (oldValue.text.length >= newValue.text.length) {
return newValue;
}
var dateText = _addSeperators(newValue.text, '/');
return newValue.copyWith(text: dateText, selection: updateCursorPosition(dateText));
}
String _addSeperators(String value, String seperator) {
value = value.replaceAll('/', '');
var newString = '';
for (int i = 0; i < value.length; i++) {
newString += value[i];
if (i == 1) {
newString += seperator;
}
if (i == 3) {
newString += seperator;
}
}
return newString;
}
TextSelection updateCursorPosition(String text) {
return TextSelection.fromPosition(TextPosition(offset: text.length));
}
}
Run Code Online (Sandbox Code Playgroud)
添加基于 Arizona1911 和 Jochem Toolenaar 版本的更新版本。
这可以防止在修改某些已输入的文本时插入符号跳转。
class DateTextFormatter extends TextInputFormatter {
static const _maxChars = 8;
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue,
TextEditingValue newValue,
) {
String separator = '/';
var text = _format(
newValue.text,
oldValue.text,
separator,
);
return newValue.copyWith(
text: text,
selection: updateCursorPosition(
oldValue,
text,
),
);
}
String _format(
String value,
String oldValue,
String separator,
) {
var isErasing = value.length < oldValue.length;
var isComplete = value.length > _maxChars + 2;
if (!isErasing && isComplete) {
return oldValue;
}
value = value.replaceAll(separator, '');
final result = <String>[];
for (int i = 0; i < min(value.length, _maxChars); i++) {
result.add(value[i]);
if ((i == 1 || i == 3) && i != value.length - 1) {
result.add(separator);
}
}
return result.join();
}
TextSelection updateCursorPosition(
TextEditingValue oldValue,
String text,
) {
var endOffset = max(
oldValue.text.length - oldValue.selection.end,
0,
);
var selectionEnd = text.length - endOffset;
return TextSelection.fromPosition(TextPosition(offset: selectionEnd));
}
}
Run Code Online (Sandbox Code Playgroud)
感谢Caseyryan/flutter_multi_formatter
| 归档时间: |
|
| 查看次数: |
4724 次 |
| 最近记录: |