How do I format EditText for currency input in Android?

The following Android code snippet shows you how to customize the input value format of an EditText component for accepting currency number. To format the input value we will create a text watcher class called MoneyTextWatcher, this class implements of the android.text.TextWatcher interface.

In the MoneyTextWatcher class we implement the afterTextChanged(EditText s) method, in this method the currency formatting takes place by adding currency symbol before the digit on numbers.

To apply this text watcher class we call the addTextChangedListener() method of the EditText object of the currency input and pass an instance of MoneyTextWatcher. Below is the working example of the activity class and the text watcher.

package org.kodejava.android;

import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

import java.math.BigDecimal;

public class MainActivity extends AppCompatActivity {
    private EditText editText;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editText = findViewById(R.id.editText);
        editText.addTextChangedListener(new MoneyTextWatcher(editText));
        editText.setText("0");

        textView = findViewById(R.id.textView);
    }

    public void doGetValue(View view) {
        BigDecimal value = MoneyTextWatcher.parseCurrencyValue(editText.getText().toString());
        textView.setText(String.valueOf(value));
    }
}

When the EditText input is changed the afterTextChanged() method of the text watcher will be called. In this method we’ll take the input text and format the input value with currency symbol and a number, this is done by the NumberFormat.getCurrencyInstance() object.

The static helper method parseCurrencyValue() will get the number part of the EditText by removing the currency symbol and return the input number.

package org.kodejava.android;

import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;

import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;
import java.util.Objects;

public class MoneyTextWatcher implements TextWatcher {
    private static final Locale locale = new Locale("id", "ID");
    private static final DecimalFormat formatter = (DecimalFormat) NumberFormat.getCurrencyInstance(locale);
    private final WeakReference<EditText> editTextWeakReference;

    public MoneyTextWatcher(EditText editText) {
        editTextWeakReference = new WeakReference<>(editText);
        formatter.setMaximumFractionDigits(0);
        formatter.setRoundingMode(RoundingMode.FLOOR);

        DecimalFormatSymbols symbol = new DecimalFormatSymbols(locale);
        symbol.setCurrencySymbol(symbol.getCurrencySymbol() + " ");
        formatter.setDecimalFormatSymbols(symbol);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    @Override
    public void afterTextChanged(Editable s) {
        EditText editText = editTextWeakReference.get();
        if (editText == null || editText.getText().toString().isEmpty()) {
            return;
        }
        editText.removeTextChangedListener(this);

        BigDecimal parsed = parseCurrencyValue(editText.getText().toString());
        String formatted = formatter.format(parsed);

        editText.setText(formatted);
        editText.setSelection(formatted.length());
        editText.addTextChangedListener(this);
    }

    public static BigDecimal parseCurrencyValue(String value) {
        try {
            String replaceRegex = String.format("[%s,.\\s]",
                    Objects.requireNonNull(formatter.getCurrency()).getSymbol(locale));
            String currencyValue = value.replaceAll(replaceRegex, "");
            currencyValue = "".equals(currencyValue) ? "0" : currencyValue;
            return new BigDecimal(currencyValue);
        } catch (Exception e) {
            Log.e("App", e.getMessage(), e);
        }
        return BigDecimal.ZERO;
    }
}

The following animation is the result of our code snippet above, and you can find to complete source code here: Android Currency EditText Example



How do I get all available currency codes?

The example presented in this code snippet show you how to get the available currency codes. We will need the locale information and use the Currency class for this example.

package org.kodejava.util;

import java.util.Currency;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

public class CurrencySymbolDemo {
    public static void main(String[] args) {
        CurrencySymbolDemo cs = new CurrencySymbolDemo();

        Map<String, String> currencies = cs.getAvailableCurrencies();
        for (String country : currencies.keySet()) {
            String currencyCode = currencies.get(country);
            System.out.println(country + " => " + currencyCode);
        }
    }

    /**
     * Get the currencies code from the available locales information.
     *
     * @return a map of currencies code.
     */
    private Map<String, String> getAvailableCurrencies() {
        Locale[] locales = Locale.getAvailableLocales();

        // We use TreeMap so that the order of the data in the map sorted
        // based on the country name.
        Map<String, String> currencies = new TreeMap<>();
        for (Locale locale : locales) {
            try {
                currencies.put(locale.getDisplayCountry(),
                        Currency.getInstance(locale).getCurrencyCode());
            } catch (Exception e) {
                // when the locale is not supported
            }
        }
        return currencies;
    }
}

You will have something like this printed on the screen:

...
Honduras => HNL
Hong Kong SAR China => HKD
Hungary => HUF
Iceland => ISK
India => INR
Indonesia => IDR
Iran => IRR
Iraq => IQD
Ireland => EUR
Isle of Man => GBP
...

How do I format a number as currency string?

Creating a financial application requires you to format number as a currency. It should include the correct thousand separator, decimal separator and the currency symbol. For this purpose you can use the NumberFormat.getCurrencyInstance() method and pass the correct Locale to get the currency format that you want.

package org.kodejava.text;

import java.text.NumberFormat;
import java.util.Locale;

public class LocaleCurrencyFormat {
    public static void main(String[] args) {
        Double number = 1500D;

        // Format currency for Canada locale in Canada locale, 
        // the decimal point symbol is a comma and currency
        // symbol is $.
        NumberFormat format = NumberFormat.getCurrencyInstance(Locale.CANADA);
        String currency = format.format(number);
        System.out.println("Currency in Canada : " + currency);

        // Format currency for Germany locale in German locale,
        // the decimal point symbol is a dot and currency symbol
        // is €.
        format = NumberFormat.getCurrencyInstance(Locale.GERMANY);
        currency = format.format(number);
        System.out.println("Currency in Germany: " + currency);
    }
}

Here is an output for the currency format using the Locale.CANADA and Locale.GERMANY.

Currency in Canada : $1,500.00
Currency in Germany: 1.500,00 €

How do I get currency symbol?

package org.kodejava.util;

import java.util.Currency;
import java.util.Locale;

public class CurrencySymbol {
    public static void main(String[] args) {
        Currency currency = Currency.getInstance(Locale.JAPAN);
        System.out.println("Japan = " + currency.getSymbol());

        currency = Currency.getInstance(Locale.UK);
        System.out.println("UK = " + currency.getSymbol());

        currency = Currency.getInstance(Locale.US);
        System.out.println("US = " + currency.getSymbol());

        currency = Currency.getInstance(new Locale("in", "ID"));
        System.out.println("Indonesia = " + currency.getSymbol());
    }
}

The result of the code snippet above:

Japan = ¥
UK = £
US = $
Indonesia = IDR