1

I have a list of currencies, with all the settings I could think of:

  {
    "code": "USD",
    "name": "United States Dollar",
    "symbol": "\$",
    "flag": "USD",
    "decimal_digits": 2,
    "number": 840,
    "name_plural": "US dollars",
    "thousands_separator": ",",
    "decimal_separator": ".",
    "space_between_amount_and_symbol": false,
    "symbol_on_left": true,
  },
  {
    "code": "EUR",
    "name": "Euro",
    "symbol": "€",
    "flag": "EUR",
    "decimal_digits": 2,
    "number": 978,
    "name_plural": "Euros",
    "thousands_separator": ".",
    "decimal_separator": ",",
    "space_between_amount_and_symbol": true,
    "symbol_on_left": false,
  }, 
  ...

Now with this I was able to write a function to format a double to a formattedPrice.

BUT the main issue is that I need a TextFormField with a given currencyCode and the text is correctly formatted. It's important that in this case the symbol should not be visible. Only the number value, correctly formatted as per the given code.

I tried quite a lot of things, tried multiple packages but couldn't get it done. Most packages need the locale or simply don't work for all cases.

I feel like this must be possible, but I'm running in circles here. Is the information for my currencies not enough? Did anyone make that work before? I feel like I can't be the only one with this issue.

If anyone can make it work with my currencies.

Example:

USD $

input: 400

expected text in field: 4,00

input: 696942

expected text in field: 6,969.42

Let me know if you need more information.

6
  • Can you share an example/image of the sample output? Commented Dec 23, 2024 at 20:04
  • 1
    Also, can you share the code you already have? Commented Dec 23, 2024 at 20:08
  • An example is important to understand what you want. Commented Dec 25, 2024 at 9:54
  • @Chris ditto on the example. Can you please provide one? By formatted do you mean with the correct decimal digits, thousands separator, and decimal separator as defined in the JSON? Commented Dec 26, 2024 at 10:29
  • @Chris, to support my answer and your issue. (If your issue persists or you decide not to use locale), you can test your case after adding the relevant font files and implementing them in your project. I suspect that it is because of the font limitation Commented Dec 27, 2024 at 3:57

1 Answer 1

0

I hope you will consider this one even if I introduce the locale here...

Using intl package

Here's what I've done to achieve currency formatting in my program before:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';

class CurrencyTest extends StatefulWidget {
  const CurrencyTest({super.key});

  @override
  State<CurrencyTest> createState() => _CurrencyTestState();
}

class _CurrencyTestState extends State<CurrencyTest> {
  final NumberFormat _dollarCurrency =
      NumberFormat.simpleCurrency(locale: 'en_US', decimalDigits: 2);
  final NumberFormat _euroCurrency =
      NumberFormat.simpleCurrency(locale: 'de-DE', decimalDigits: 2);

  final _dollar = TextEditingController();
  final _euro = TextEditingController();

  double _dollarValue = 0.00;
  double _euroValue = 0.00;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Currency Test'),
      ),
      body: Center(
          child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(_dollarCurrency.format(_dollarValue)),
          TextFormField(
            controller: _dollar,
          ),
          ElevatedButton(
              onPressed: () {
                setState(() {
                  _dollarValue = double.parse(_dollar.text);
                });
              },
              child: Text('Format Dollar')),
          SizedBox(
            height: 8.0,
          ),
          Divider(),
          SizedBox(
            height: 8.0,
          ),
          Text(_euroCurrency.format(_euroValue)),
          TextFormField(
            controller: _euro,
          ),
          ElevatedButton(
              onPressed: () {
                setState(() {
                  _euroValue = double.parse(_euro.text);
                });
              },
              child: Text('Format Euro')),
        ],
      )),
    );
  }
}

This is the output from the given code snippet:

img

However, if you have any other currency symbols to use in your project, you may find it difficult to represent some of the currency symbols. The root cause is the font limitations.

According to my research, Noto Sans font is one of the best examples that has a wide range of currency symbol compatibility.

But for me, I did it in a way to achieve more currency range compatibility.

Here's what I've done to achieve the solution against the possible given case issues:

I download and integrate the font into my project's assets:

assets

Of course, I added it in pubspec.yaml file:

# The following section is specific to Flutter packages.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  assets:
    - assets/
    - assets/images/

  fonts: #Popularity based on total views as of 10/15/2024 from Google fonts
    - family: roboto #Christian Robertson designer; #27,862,326,785,287 total views
      fonts:
        - asset: assets/fonts/Roboto-Regular.ttf
    - family: open-sans #Steve Matteson designer; #15,397,682,424,627 total views
      fonts:
        - asset: assets/fonts/OpenSans-Regular.ttf
    - family: lato #Łukasz Dziedzic designer; #4,283,458,136,657 total views
      fonts:
        - asset: assets/fonts/Lato-Regular.ttf
    - family: montserrat #Julieta Ulanovsky, Sol Matas, Juan Pablo del Peral, Jacques Le Bailly designer; #3,270,167,111,315 total views
      fonts:
        - asset: assets/fonts/Montserrat-Regular.ttf
    - family: roboto-condensed #Christian Robertson designer; #2,222,596,609,812 total views
      fonts:
        - asset: assets/fonts/RobotoCondensed-Regular.ttf
    - family: oswald #Vernon Adams, Kalapi Gajjar, Cyreal designer; #2,015,317,760,078 total views
      fonts:
        - asset: assets/fonts/Oswald-Regular.ttf
    - family: poppins #Indian Type Foundry, Jonny Pinhorn, Ninad Kale designer; #1,581,285,338,851 total views
      fonts:
        - asset: assets/fonts/Poppins-Regular.ttf
    - family: slabo-27px #John Hudson designer; #1,093,631,502,304 total views
      fonts:
        - asset: assets/fonts/Slabo27px-Regular.ttf
    - family: noto-sans #Google designer; #899,099,900,620 total views
      fonts:
        - asset: assets/fonts/NotoSans-Regular.ttf
    - family: roboto-mono #Christian Robertson designer; #896,237,217,528 total views
      fonts:
        - asset: assets/fonts/RobotoMono-Regular.ttf
    - family: merriweather #Sorkin Type designer; #768,745,849,669 total views
      fonts:
        - asset: assets/fonts/Merriweather-Regular.ttf


  # To add assets to your application, add an assets section, like this:
  # assets:
  #   - images/a_dot_burr.jpeg
  #   - images/a_dot_ham.jpeg

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/to/resolution-aware-images

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/to/asset-from-package

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/to/font-from-package

I've included the comments from it to serve as guidelines.

Then, I've applied the added fonts based on my use-case conditions.

If I am using these configurations in my main.dart file,

themeMode: ThemeMode.system,
theme: lightTheme, // Light theme
darkTheme: darkTheme, // Dark theme

So I set this up (in my case, I use roboto in fontFamily property):

final ThemeData lightTheme = ThemeData(
  fontFamily: 'roboto',
  fontFamilyFallback: const [
    'lato',
    'montserrat',
    'roboto-condensed',
    'noto-sans',
    'merriweather'
  ],
  useMaterial3: true,
  // other theme data
);

final ThemeData darkTheme = ThemeData(
  fontFamily: 'roboto',
  fontFamilyFallback: const [
    'lato',
    'montserrat',
    'roboto-condensed',
    'noto-sans',
    'merriweather'
  ],
  useMaterial3: true,
  // other theme data
);

Or if I want to directly apply the font in the parent widget:

@override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        fontFamily: 'roboto',
        fontFamilyFallback: const [
          'lato',
          'montserrat',
          'roboto-condensed',
          'noto-sans',
          'merriweather'
        ],
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Currency Test'),
        ),
        body: Center(
            child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(_dollarCurrency.format(_dollarValue)),
            TextFormField(
              controller: _dollar,
            ),
            ElevatedButton(
                onPressed: () {
                  setState(() {
                    _dollarValue = double.parse(_dollar.text);
                  });
                },
                child: Text('Format Dollar')),
            SizedBox(
              height: 8.0,
            ),
            Divider(),
            SizedBox(
              height: 8.0,
            ),
            Text(_euroCurrency.format(_euroValue)),
            TextFormField(
              controller: _euro,
            ),
            ElevatedButton(
                onPressed: () {
                  setState(() {
                    _euroValue = double.parse(_euro.text);
                  });
                },
                child: Text('Format Euro')),
          ],
        )),
      ),
    );
  }

For simplified removal of the leading and trailing currency symbols:

for dollar:

setState(() {
  _dollarValue = double.parse(_dollar.text);
  debugPrint('Dollar: ${_dollarCurrency.format(_dollarValue).replaceAll('\$', '')}'); // using of replaceAll
  debugPrint('Dollar: ${_dollarCurrency.format(_dollarValue).substring(1)}'); // using of substring for dollar
});

for euro:

setState(() {
  _euroValue = double.parse(_euro.text);
  debugPrint(
      'Euro: ${_euroCurrency.format(_euroValue).replaceAll('€', '')}'); // using of replaceAll
  debugPrint(
      'Euro: ${_euroCurrency.format(_euroValue).substring(0, _euroCurrency.format(_euroValue).length - 1)}'); // using of substring for euro
});

I am hoping that you could use these guidelines to support your debugging process.

I hope it helps!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.