Я пытаюсь отобразить введенное пользователем двойное число (может быть без десятичной точки и далее) в виде форматированного значения, например. 123456789012.1234
как 12345,67,89,012.1234
, используя не западную систему нумерации, а систему нумерации Индийского субконтинента, как показано. Желательно без запятых после крор.
С помощью пакета intl
я мог бы отображать форматированный вывод, но мне также нужно форматировать вводимые пользователем данные в поле ввода текста. И это мне так и не удалось заставить работать.
Я написал следующий минимальный код, чтобы показать мою проблему. Здесь, когда я ввожу 123, а затем 4, в правильном месте появляется запятая (т. е. 1234), но затем, когда я последовательно ввожу пятую цифру, т. е. 5, отображается только 0, что является ошибкой.
Как я могу это исправить?
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
final _controller = TextEditingController();
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('intl Formatter With Formatted Text Field'),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: TextField(
controller: _controller,
keyboardType: TextInputType.number,
onChanged: (value) {
NumberFormat numberFormat = NumberFormat("#,##,##,###.########");
final formattedValue =
numberFormat.format(double.tryParse(value) ?? 0.0);
_controller.value = TextEditingValue(
text: formattedValue,
);
},
),
),
),
);
}
}
Проблема с вашим текущим кодом заключается в том, что значение содержит запятую (,
) после ввода 1234
. При вводе следующего символа (например, 5
) 1,2345
передается в double.tryParse, который не может проанализировать значение, поскольку оно содержит запятую, а синтаксический анализатор учитывает только точки (.
) для разделения десятичных знаков.
Один из вариантов обойти это — удалить все запятые перед передачей значения double.tryParse
, например:
value = value.replaceAll(",", "");
Вот пример dart.dev.
Благодаря этому решению запятые появляются в правильных позициях. Но я не смог дополнить свое двойное число десятичными и последующими цифрами. TextField не принимает точку '.' во входе. Есть ли решение этой проблемы? (Спасибо за ваш ответ, который частично решил мою проблему.)
Еще раз спасибо за ваше решение. +1 . С помощью вашего ответа мне удалось получить то, что мне нужно, с дополнительными кодами, которые вы можете найти в моем ответе.
Мне нужно было отформатировать входное двойное значение в TextField
, чтобы оно отображалось в индийском формате нумерации. В этом вопросе я разместил свой минимальный код, который пытался сделать это не полностью. С помощью формы ответа от @frankenapps здесь, а также методом проб и ошибок мне наконец удалось получить то, что я хотел.
Приветствуются дополнительные предложения по улучшению кода или совершенно новый ответ.
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
final _controller = TextEditingController();
void main() => runApp(MyApp());
class RememberMyValue {
static String value_previous_or_this_instance = "";
}
class MyApp extends StatelessWidget {
String parseMyNumber(String str) {
// Function to parse only positive numbers (without any prefix):
RegExp myNumber01 = RegExp(r'^[0-9]+$');
RegExp myNumber02 = RegExp(r'^[0-9]+\.$');
RegExp myNumber03 = RegExp(r'^[0-9]+\.[0-9]+$');
NumberFormat numberFormat01_and_02 = NumberFormat("#,##,##,###");
// The result of eight #s after the decimal point is that users will be able
// to input only eight digits after decimal.
NumberFormat numberFormat03 = NumberFormat("#,##,##,###.########");
// We want to stop taking digits after 8 digits succeding the decimal dot
// in the user input in consistent with the numberFormat03 formatting. We
// declare the following constant for that.
const int maxDigitsAfterDecimalPeroid = 8;
const int countOfAPeriod = 1;
print("########## str=$str");
String lastChar = "";
String extractedString = "";
int digitsBeforePeriod = str.indexOf(".");
if (str.length >
digitsBeforePeriod + countOfAPeriod + maxDigitsAfterDecimalPeroid) {
extractedString = str.substring(
0, str.indexOf(".") + (maxDigitsAfterDecimalPeroid + 1));
str = extractedString;
}
print("########## extracted_string=$extractedString");
if (str.isEmpty) {
return "";
}
if (myNumber01.hasMatch(str)) {
return numberFormat01_and_02.format(int.parse(str));
} else {
if (myNumber02.hasMatch(str)) {
// Here str.replaceAll(".", "") chops the trailing dot from the input, and
// finally the return statement is interpolated such that there is a dot
// appended at the end of the number.
return "${numberFormat01_and_02.format(int.parse(str.replaceAll(".", "")))}.";
} else {
if (myNumber03.hasMatch(str)) {
lastChar = str[str.length - 1];
print("########## lastChar=$lastChar");
if (lastChar == "0") {
String subStringBeforePeriod = "";
String subStringAfterPeriod = "";
String tmpStr = "";
int indexOfPeriod = str.indexOf(".");
subStringBeforePeriod = str.substring(0, indexOfPeriod);
print("########## subStringBeforePeriod=$subStringBeforePeriod");
subStringAfterPeriod = str.substring(indexOfPeriod + 1, str.length);
print("########## subStringAfterPeriod=$subStringAfterPeriod");
print("########## str with last char possibly = $str");
// return numberFormat03.format(double.parse(str)) + lastChar;
tmpStr =
numberFormat01_and_02.format(int.parse(subStringBeforePeriod));
print("tmpStr=$tmpStr");
// return numberFormat03.format(double.parse(str)) + lastChar;
return "${tmpStr}.${subStringAfterPeriod}";
}
return numberFormat03.format(double.parse(str));
} else {
return "NaN";
}
}
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('intl Formatter With Formatted Text Field'),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: TextField(
controller: _controller,
keyboardType: TextInputType.number,
onChanged: (value) {
print("########## value=$value");
value = value.replaceAll(",", "");
String myFormattedNumber = "";
myFormattedNumber = parseMyNumber(value);
if (myFormattedNumber != "NaN") {
RememberMyValue.value_previous_or_this_instance =
myFormattedNumber;
print(
"########## value_previous_or_this_instance = ${RememberMyValue.value_previous_or_this_instance}");
} else {
print("########## NaN");
}
_controller.value = TextEditingValue(
text: RememberMyValue.value_previous_or_this_instance,
);
print("########## _controller.text = ${_controller.text}");
},
),
),
),
);
}
}
Чтобы отформатировать пользовательский ввод во Flutter, вам нужно будет создать собственный форматтер. Такой подход даст вам больше контроля.