Как отформатировать двойной ввод пользователя в TextField при вводе пользователем во Flutter?

Я пытаюсь отобразить введенное пользователем двойное число (может быть без десятичной точки и далее) в виде форматированного значения, например. 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,
              );
            },
          ),
        ),
      ),
    );
  }
}

Чтобы отформатировать пользовательский ввод во Flutter, вам нужно будет создать собственный форматтер. Такой подход даст вам больше контроля.

Tomiwa Idowu 20.07.2024 04:53
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
133
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Проблема с вашим текущим кодом заключается в том, что значение содержит запятую (,) после ввода 1234. При вводе следующего символа (например, 5) 1,2345 передается в double.tryParse, который не может проанализировать значение, поскольку оно содержит запятую, а синтаксический анализатор учитывает только точки (.) для разделения десятичных знаков.

Один из вариантов обойти это — удалить все запятые перед передачей значения double.tryParse, например:

value = value.replaceAll(",", "");

Вот пример dart.dev.

Благодаря этому решению запятые появляются в правильных позициях. Но я не смог дополнить свое двойное число десятичными и последующими цифрами. TextField не принимает точку '.' во входе. Есть ли решение этой проблемы? (Спасибо за ваш ответ, который частично решил мою проблему.)

rusty 21.07.2024 03:18

Еще раз спасибо за ваше решение. +1 . С помощью вашего ответа мне удалось получить то, что мне нужно, с дополнительными кодами, которые вы можете найти в моем ответе.

rusty 22.07.2024 11:07
Ответ принят как подходящий

Мне нужно было отформатировать входное двойное значение в 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}");
            },
          ),
        ),
      ),
    );
  }
}

Снимок:

Другие вопросы по теме