描述
对于金额等的输入,常常要求TextField限制输入为小数,可使用以下约束:
inputFormatters: [
WhitelistingTextInputFormatter(RegExp("[0-9.]")), //只允许输入小数
],
但这种限制会有问题,比如可以输入0.1.1这种其实就不是小数了,并且不能限制小数点的输入位数。
限制输入为合法小数
继承TextInputFormatter类,重写formatEditUpdate方法:
import 'package:flutter/services.dart';
class XNumberTextInputFormatter extends TextInputFormatter {
int _maxIntegerLength;
int _maxDecimalLength;
bool _isAllowDecimal;
/// [maxIntegerLength]限定整数的最大位数,为null时不限
/// [maxDecimalLength]限定小数点的最大位数,为null时不限
/// [isAllowDecimal]是否可以为小数,默认是可以为小数,也就是可以输入小数点
XNumberTextInputFormatter(
{int maxIntegerLength, int maxDecimalLength, bool isAllowDecimal = true})
: _maxIntegerLength = maxIntegerLength,
_maxDecimalLength = maxDecimalLength,
_isAllowDecimal = isAllowDecimal;
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
String value = newValue.text?.trim(); //去掉前后空格
int selectionIndex = newValue.selection.end;
if (_isAllowDecimal) {
if (value == '.') {
value = '0.';
selectionIndex++;
} else if (value != '' && _isToDoubleError(value)) {
//不是double输入数据
return _oldTextEditingValue(oldValue);
}
//包含小数点
if (value.contains('.')) {
int pointIndex = value.indexOf('.');
String beforePoint = value.substring(0, pointIndex);
// print('$beforePoint');
String afterPoint = value.substring(pointIndex + 1, value.length);
// print('$afterPoint');
//小数点前面没内容补0
if (beforePoint.length == 0) {
value = '0.${afterPoint ?? ''}';
selectionIndex++;
} else {
//限定整数位数
if (null != _maxIntegerLength) {
if (beforePoint.length > _maxIntegerLength) {
return _oldTextEditingValue(oldValue);
}
}
}
//限定小数点位数
if (null != _maxDecimalLength) {
if (afterPoint.length > _maxDecimalLength) {
return _oldTextEditingValue(oldValue);
}
}
} else {
//限定整数位数
if (null != _maxIntegerLength) {
if (value.length > _maxIntegerLength) {
return _oldTextEditingValue(oldValue);
}
}
}
} else {
if (value.contains('.') ||
(value != '' && _isToDoubleError(value)) ||
(null!=_maxIntegerLength&&value.length > _maxIntegerLength)) {
return _oldTextEditingValue(oldValue);
}
}
return TextEditingValue(
text: value,
selection: TextSelection.collapsed(offset: selectionIndex),
);
}
///返回旧的输入内容
TextEditingValue _oldTextEditingValue(TextEditingValue oldValue) {
return TextEditingValue(
text: oldValue.text,
selection: TextSelection.collapsed(offset: oldValue.selection.end),
);
}
///输入内容不能解析成double
bool _isToDoubleError(String value) {
try {
double.parse(value);
} catch (e) {
return true;
}
return false;
}
}
示例
TextField(
//设置键盘可录入为小数
keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [
XNumberTextInputFormatter(
maxIntegerLength: null, maxDecimalLength: 2,isAllowDecimal: true),
],
onChanged: (value) {
print(value);
print(double.tryParse(value));
},
),
温馨提示:
- keyboardType: TextInputType.numberWithOptions(decimal: true) 控制弹出键盘为带小数点的数字键盘,不是必须的,为了体验更好;
- inputFormatters:对输入要显示在输入框的内容进行处理;