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
How to Automatically add thousand separators as number is input in 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
以下代码的特征
Puts thousand separator in
EditText
as it's text changes.adds
0.
Automatically when pressed period (.) At First.Ignores
0
input at Beginning.
在
EditText
文本更改时放入千位分隔符。0.
按下句号时自动添加(.) 首先。忽略
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 EditText
as follows
在你EditText
的下面使用这个类
editText.addTextChangedListener(new NumberTextWatcherForThousand(editText));
To get the input as plain Double Text
将输入作为纯双文本
Use the trimCommaOfString
method of the same class like this
trimCommaOfString
像这样使用同一个类的方法
NumberTextWatcherForThousand.trimCommaOfString(editText.getText().toString())
回答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 TextWatcher
and in the afterTextChanged()
method format the EditText
view with the following logic:
总结上面的链接,TextWatcher
在afterTextChanged()
方法中使用 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:
改进:
- Thousands separators and Decimal markers are locale aware i.e. they are used accordingly to the
Locale
of the device. - The cursor position doesn't change after deleting or adding elements in the middle also (In his answer cursor was reset to the end).
- The overall quality of the code has been improved specially the
getDecimalFormattedString
method.
- 千位分隔符和十进制标记是本地化的,即它们根据
Locale
设备的类型使用。 - 在中间删除或添加元素后,光标位置也不会改变(在他的回答中,光标已重置到末尾)。
- 代码的整体质量得到了特别的改进
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 ThousandNumberEditText
class
这是我的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 comma
to 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上使用它。祝你好运