描述
對(duì)于金額等的輸入,常常要求TextField限制輸入為小數(shù),可使用以下約束:
inputFormatters: [
WhitelistingTextInputFormatter(RegExp("[0-9.]")), //只允許輸入小數(shù)
],
但這種限制會(huì)有問(wèn)題兄纺,比如可以輸入0.1.1這種其實(shí)就不是小數(shù)了瓶盛,并且不能限制小數(shù)點(diǎn)的輸入位數(shù)娱挨。
限制輸入為合法小數(shù)
繼承TextInputFormatter類鉴嗤,重寫(xiě)formatEditUpdate方法:
import 'package:flutter/services.dart';
class XNumberTextInputFormatter extends TextInputFormatter {
int _maxIntegerLength;
int _maxDecimalLength;
bool _isAllowDecimal;
/// [maxIntegerLength]限定整數(shù)的最大位數(shù)堵漱,為null時(shí)不限
/// [maxDecimalLength]限定小數(shù)點(diǎn)的最大位數(shù)祷愉,為null時(shí)不限
/// [isAllowDecimal]是否可以為小數(shù)艰山,默認(rèn)是可以為小數(shù)湖雹,也就是可以輸入小數(shù)點(diǎn)
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輸入數(shù)據(jù)
return _oldTextEditingValue(oldValue);
}
//包含小數(shù)點(diǎn)
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');
//小數(shù)點(diǎn)前面沒(méi)內(nèi)容補(bǔ)0
if (beforePoint.length == 0) {
value = '0.${afterPoint ?? ''}';
selectionIndex++;
} else {
//限定整數(shù)位數(shù)
if (null != _maxIntegerLength) {
if (beforePoint.length > _maxIntegerLength) {
return _oldTextEditingValue(oldValue);
}
}
}
//限定小數(shù)點(diǎn)位數(shù)
if (null != _maxDecimalLength) {
if (afterPoint.length > _maxDecimalLength) {
return _oldTextEditingValue(oldValue);
}
}
} else {
//限定整數(shù)位數(shù)
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),
);
}
///返回舊的輸入內(nèi)容
TextEditingValue _oldTextEditingValue(TextEditingValue oldValue) {
return TextEditingValue(
text: oldValue.text,
selection: TextSelection.collapsed(offset: oldValue.selection.end),
);
}
///輸入內(nèi)容不能解析成double
bool _isToDoubleError(String value) {
try {
double.parse(value);
} catch (e) {
return true;
}
return false;
}
}
示例
TextField(
//設(shè)置鍵盤(pán)可錄入為小數(shù)
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) 控制彈出鍵盤(pán)為帶小數(shù)點(diǎn)的數(shù)字鍵盤(pán),不是必須的曙搬,為了體驗(yàn)更好摔吏;
- inputFormatters:對(duì)輸入要顯示在輸入框的內(nèi)容進(jìn)行處理;