Android 如何在 EditText 中输入数字时自动添加千位分隔符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12338445/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 10:26:32  来源:igfitidea点击:

How to Automatically add thousand separators as number is input in EditText

androidandroid-layoutandroid-emulatorandroid-edittext

提问by Asiimwe

Im creating a convertor application, I want to set the EditText so that when the user is inputting the number to be converted, a thousand separator (,) should be added automaticaaly in realtime to the number once it increaments by 3 figures.....thousand, million, billion etc and when erased to below 4 figures the number goes back to normal. Any help? Thank You.

我正在创建一个转换器应用程序,我想设置 EditText 以便当用户输入要转换的数字时,一旦数字增加了 3 个数字,就应该实时将千位分隔符 (,) 添加到数字中.... .千、百万、十亿等,当擦除到 4 位数以下时,数字会恢复正常。有什么帮助吗?谢谢你。

采纳答案by Dheeraj Vepakomma

You can use String.format()in a TextWatcher. The comma in the format specifier does the trick.

您可以String.format()TextWatcher. 格式说明符中的逗号可以解决问题。

This does not work for floating point input. And be careful not to set an infinite loop with the TextWatcher.

这不适用于浮点输入。并注意不要使用 TextWatcher 设置无限循环。

public void afterTextChanged(Editable view) {
    String s = null;
    try {
        // The comma in the format specifier does the trick
        s = String.format("%,d", Long.parseLong(view.toString()));
    } catch (NumberFormatException e) {
    }
    // Set s back to the view after temporarily removing the text change listener
}

回答by Shree Krishna

Solved The Issue Finally

最终解决了问题

Even-though It is too late answer. I've researched much to accomplish the task To get the proper result but could not. So I finally solved the issue we were searching and provided this answer to the google searchers for saving their times on searching.

即使 - 虽然现在回答为时已晚。我已经研究了很多来完成任务以获得正确的结果但不能。所以我终于解决了我们正在搜索的问题,并向谷歌搜索者提供了这个答案,以节省他们的搜索时间。

Fetures of the following codes

以下代码的特征

  1. Puts thousand separator in EditTextas it's text changes.

  2. adds 0.Automatically when pressed period (.) At First.

  3. Ignores 0input at Beginning.

  1. EditText文本更改时放入千位分隔符。

  2. 0.按下句号时自动添加(.) 首先。

  3. 忽略0开始时的输入。

Just copy the following Class named

只需复制以下名为的类

NumberTextWatcherForThousandwhich implementsTextWatcher

NumberTextWatcherForThousand工具TextWatcher

import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import java.util.StringTokenizer;

/**
 * Created by skb on 12/14/2015.
 */
public class NumberTextWatcherForThousand implements TextWatcher {

    EditText editText;


    public NumberTextWatcherForThousand(EditText editText) {
        this.editText = editText;


    }

    @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) {
        try
        {
            editText.removeTextChangedListener(this);
            String value = editText.getText().toString();


            if (value != null && !value.equals(""))
            {

                if(value.startsWith(".")){
                    editText.setText("0.");
                }
                if(value.startsWith("0") && !value.startsWith("0.")){
                    editText.setText("");

                }


                String str = editText.getText().toString().replaceAll(",", "");
                if (!value.equals(""))
                editText.setText(getDecimalFormattedString(str));
                editText.setSelection(editText.getText().toString().length());
            }
            editText.addTextChangedListener(this);
            return;
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            editText.addTextChangedListener(this);
        }

    }

    public static String getDecimalFormattedString(String value)
    {
        StringTokenizer lst = new StringTokenizer(value, ".");
        String str1 = value;
        String str2 = "";
        if (lst.countTokens() > 1)
        {
            str1 = lst.nextToken();
            str2 = lst.nextToken();
        }
        String str3 = "";
        int i = 0;
        int j = -1 + str1.length();
        if (str1.charAt( -1 + str1.length()) == '.')
        {
            j--;
            str3 = ".";
        }
        for (int k = j;; k--)
        {
            if (k < 0)
            {
                if (str2.length() > 0)
                    str3 = str3 + "." + str2;
                return str3;
            }
            if (i == 3)
            {
                str3 = "," + str3;
                i = 0;
            }
            str3 = str1.charAt(k) + str3;
            i++;
        }

    }

    public static String trimCommaOfString(String string) {
//        String returnString;
        if(string.contains(",")){
            return string.replace(",","");}
        else {
            return string;
        }

    }
}

Use This Class on your EditTextas follows

在你EditText的下面使用这个类

editText.addTextChangedListener(new NumberTextWatcherForThousand(editText));

To get the input as plain Double Text

将输入作为纯双文本

Use the trimCommaOfStringmethod of the same class like this

trimCommaOfString像这样使用同一个类的方法

NumberTextWatcherForThousand.trimCommaOfString(editText.getText().toString())

Git

吉特

回答by user2261183

  public static String doubleToStringNoDecimal(double d) {
        DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US);;
        formatter .applyPattern("#,###");
        return formatter.format(d);
    }

回答by Adam Hurwitz

This sample appdeconstructs formatting numbers clearly.

这个示例应用程序清楚地解构了格式化数字。

To summarize the link above, use a TextWatcherand in the afterTextChanged()method format the EditTextview with the following logic:

总结上面的链接,TextWatcherafterTextChanged()方法中使用 a and使用EditText以下逻辑格式化视图:

@Override
public void afterTextChanged(Editable s) {
    editText.removeTextChangedListener(this);

    try {
        String originalString = s.toString();

        Long longval;
        if (originalString.contains(",")) {
            originalString = originalString.replaceAll(",", "");
        }
        longval = Long.parseLong(originalString);

        DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US);
        formatter.applyPattern("#,###,###,###");
        String formattedString = formatter.format(longval);

        //setting text after format to EditText
        editText.setText(formattedString);
        editText.setSelection(editText.getText().length());
    } catch (NumberFormatException nfe) {
        nfe.printStackTrace();
    }

    editText.addTextChangedListener(this);
}

回答by dr0pdb

I know i am very late to the party but it may be very useful for future users. My answer is an extension of Shree Krishna's answer.

我知道我参加聚会很晚,但它可能对未来的用户非常有用。我的回答是Shree Krishna回答的延伸。

Improvements:

改进:

  1. Thousands separators and Decimal markers are locale aware i.e. they are used accordingly to the Localeof the device.
  2. The cursor position doesn't change after deleting or adding elements in the middle also (In his answer cursor was reset to the end).
  3. The overall quality of the code has been improved specially the getDecimalFormattedStringmethod.
  1. 千位分隔符和十进制标记是本地化的,即它们根据Locale设备的类型使用。
  2. 在中间删除或添加元素后,光标位置也不会改变(在他的回答中,光标已重置到末尾)。
  3. 代码的整体质量得到了特别的改进getDecimalFormattedString

Code:

代码:

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

    import java.text.DecimalFormat;


    /**
     * Created by srv_twry on 4/12/17.
     * Source: https://stackoverflow.com/a/34265406/137744
     * The custom TextWatcher that automatically adds thousand separators in EditText.
     */

    public class ThousandSeparatorTextWatcher implements TextWatcher {

        private DecimalFormat df;
        private EditText editText;
        private static String thousandSeparator;
        private static String decimalMarker;
        private int cursorPosition;

        public ThousandSeparatorTextWatcher(EditText editText) {
            this.editText = editText;
            df = new DecimalFormat("#,###.##");
            df.setDecimalSeparatorAlwaysShown(true);
            thousandSeparator = Character.toString(df.getDecimalFormatSymbols().getGroupingSeparator());
            decimalMarker = Character.toString(df.getDecimalFormatSymbols().getDecimalSeparator());
        }

        @Override
        public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
            cursorPosition = editText.getText().toString().length() - editText.getSelectionStart();
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

        @Override
        public void afterTextChanged(Editable s) {
            try {
                editText.removeTextChangedListener(this);
                String value = editText.getText().toString();

                if (value != null && !value.equals("")) {
                    if (value.startsWith(decimalMarker)) {
                        String text = "0" + decimalMarker;
                        editText.setText(text);
                    }
                    if (value.startsWith("0") && !value.startsWith("0" + decimalMarker)) {
                        int index = 0;
                        while (index < value.length() && value.charAt(index) == '0') {
                            index++;
                        }
                        String newValue = Character.toString(value.charAt(0));
                        if (index != 0) {
                            newValue = value.charAt(0) + value.substring(index);
                        }
                        editText.setText(newValue);
                    }
                    String str = editText.getText().toString().replaceAll(thousandSeparator, "");
                    if (!value.equals("")) {
                        editText.setText(getDecimalFormattedString(str));
                    }
                    editText.setSelection(editText.getText().toString().length());
                }

                //setting the cursor back to where it was
                editText.setSelection(editText.getText().toString().length() - cursorPosition);
                editText.addTextChangedListener(this);
            } catch (Exception ex) {
                ex.printStackTrace();
                editText.addTextChangedListener(this);
            }
        }

        private static String getDecimalFormattedString(String value) {

            String[] splitValue = value.split("\.");
            String beforeDecimal = value;
            String afterDecimal = null;
            String finalResult = "";

            if (splitValue.length == 2) {
                beforeDecimal = splitValue[0];
                afterDecimal = splitValue[1];
            }

            int count = 0;
            for (int i = beforeDecimal.length() - 1; i >= 0 ; i--) {
                finalResult = beforeDecimal.charAt(i) + finalResult;
                count++;
                if (count == 3 && i > 0) {
                    finalResult = thousandSeparator + finalResult;
                    count = 0;
                }
            }

            if (afterDecimal != null) {
                finalResult = finalResult + decimalMarker + afterDecimal;
            }

            return finalResult;
        }

        /*
        * Returns the string after removing all the thousands separators.
        * */
        public static String getOriginalString(String string) {
            return string.replace(thousandSeparator,"");
        }
    }

回答by vlazzle

This solution has some advantage over other answers. For example, it keeps the user's cursor position even if they edit the beginning or middle of the number. Other solutions always jump the cursor to the end of the number. It handles decimals and whole numbers, as well as locales that use characters other than .for the decimal separator and ,for the thousands grouping separator.

与其他答案相比,此解决方案具有一些优势。例如,即使用户编辑数字的开头或中间,它也会保持用户的光标位置。其他解决方案总是将光标跳转到数字的末尾。它处理小数和整数,以及使用除.小数分隔符和,千位分组分隔符以外的字符的语言环境。

class SeparateThousands(val groupingSeparator: String, val decimalSeparator: String) : TextWatcher {

    private var busy = false

    override fun afterTextChanged(s: Editable?) {
        if (s != null && !busy) {
            busy = true

            var place = 0

            val decimalPointIndex = s.indexOf(decimalSeparator)
            var i = if (decimalPointIndex == -1) {
                s.length - 1
            } else {
                decimalPointIndex - 1
            }
            while (i >= 0) {
                val c = s[i]
                if (c == groupingSeparator[0] ) {
                    s.delete(i, i + 1)
                } else {
                    if (place % 3 == 0 && place != 0) {
                        // insert a comma to the left of every 3rd digit (counting from right to
                        // left) unless it's the leftmost digit
                        s.insert(i + 1, groupingSeparator)
                    }
                    place++
                }
                i--
            }

            busy = false
        }
    }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
    }

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
    }
}

Then in xml:

然后在xml中:

  <EditText
    android:id="@+id/myNumberField"
    android:digits=",.0123456789"
    android:inputType="numberDecimal"
    .../>

And finally register the watcher:

最后注册观察者:

findViewById(R.id.myNumberField).addTextChangedListener(
    SeparateThousands(groupingSeparator, decimalSeparator))

To handle . vs , in different locales use groupingSeparator and decimalSeparator, which can come from DecimalFormatSymbols or localized strings.

处理 。vs ,在不同的语言环境中使用 groupingSeparator 和 decimalSeparator,它们可以来自 DecimalFormatSymbols 或本地化的字符串。

回答by Phan Van Linh

Here is my ThousandNumberEditTextclass

这是我的ThousandNumberEditText

public class ThousandNumberEditText extends android.support.v7.widget.AppCompatEditText {
    // TODO: 14/09/2017 change it if you want 
    private static final int MAX_LENGTH = 20;
    private static final int MAX_DECIMAL = 3;

    public ThousandNumberEditText(Context context) {
        this(context, null);
    }

    public ThousandNumberEditText(Context context, AttributeSet attrs) {
        this(context, attrs, android.support.v7.appcompat.R.attr.editTextStyle);
    }

    public ThousandNumberEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        addTextChangedListener(new ThousandNumberTextWatcher(this));
        setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
        setFilters(new InputFilter[] { new InputFilter.LengthFilter(MAX_LENGTH) });
        setHint("0"); // TODO: 14/09/2017 change it if you want 
    }

    private static class ThousandNumberTextWatcher implements TextWatcher {

        private EditText mEditText;

        ThousandNumberTextWatcher(EditText editText) {
            mEditText = editText;
        }

        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void afterTextChanged(Editable editable) {
            String originalString = editable.toString();
            String cleanString = originalString.replaceAll("[,]", "");
            if (cleanString.isEmpty()) {
                return;
            }
            String formattedString = getFormatString(cleanString);

            mEditText.removeTextChangedListener(this);
            mEditText.setText(formattedString);
            mEditText.setSelection(mEditText.getText().length());
            mEditText.addTextChangedListener(this);
        }

        /**
         * Return the format string
         */
        private String getFormatString(String cleanString) {
            if (cleanString.contains(".")) {
                return formatDecimal(cleanString);
            } else {
                return formatInteger(cleanString);
            }
        }

        private String formatInteger(String str) {
            BigDecimal parsed = new BigDecimal(str);
            DecimalFormat formatter;
            formatter = new DecimalFormat("#,###");
            return formatter.format(parsed);
        }

        private String formatDecimal(String str) {
            if (str.equals(".")) {
                return ".";
            }
            BigDecimal parsed = new BigDecimal(str);
            DecimalFormat formatter;
            formatter =
                    new DecimalFormat("#,###." + getDecimalPattern(str)); //example patter #,###.00
            return formatter.format(parsed);
        }

        /**
         * It will return suitable pattern for format decimal
         * For example: 10.2 -> return 0 | 10.23 -> return 00 | 10.235 -> return 000
         */
        private String getDecimalPattern(String str) {
            int decimalCount = str.length() - 1 - str.indexOf(".");
            StringBuilder decimalPattern = new StringBuilder();
            for (int i = 0; i < decimalCount && i < MAX_DECIMAL; i++) {
                decimalPattern.append("0");
            }
            return decimalPattern.toString();
        }
    }
}

Using

使用

<.ThousandNumberEditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    />

回答by Alireza K

You can use this method:

您可以使用此方法:

myEditText.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }

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

                    String input = s.toString();

                    if (!input.isEmpty()) {

                        input = input.replace(",", "");

                        DecimalFormat format = new DecimalFormat("#,###,###");
                        String newPrice = format.format(Double.parseDouble(input));


                        myEditText.removeTextChangedListener(this); //To Prevent from Infinite Loop

                        myEditText.setText(newPrice);
                        myEditText.setSelection(newPrice.length()); //Move Cursor to end of String

                        myEditText.addTextChangedListener(this);
                    }

                }

                @Override
                public void afterTextChanged(final Editable s) {
                }
            });

And to get original text use this:

要获取原始文本,请使用以下命令:

String input = myEditText.getText().toString();
input = input.replace(",", "");

回答by Zohab Ali

I just wanted commato be placed and this is working for me:

我只是想comma被安置,这对我有用:

String.format("%,.2f", myValue);

回答by Mohammad Hadi

you can use this code in many ways in your program, you give it a string and it separate each three from right and place space there.

你可以在你的程序中以多种方式使用这段代码,你给它一个字符串,它将每三个从右边分开并在那里放置空间。

private String Spacer(String number){
    StringBuilder strB = new StringBuilder();
    strB.append(number);
    int Three = 0;

    for(int i=number.length();i>0;i--){
        Three++;
        if(Three == 3){
            strB.insert(i-1, " ");
            Three = 0;
        }
    }
    return strB.toString();
}// end Spacer()

u can change it a bit and use it ontextchangelistener. good luck

你可以稍微改变它并在textchangelistener上使用它。祝你好运