我正在创建一个转换器应用程序,我想设置EditText,这样当用户输入要转换的数字时,一旦它增加3个数字,就应该实时自动添加一千个分隔符(,)。 ......千万,百万,亿等 当擦除到4以下时,数字会恢复正常。 有帮助吗? 谢谢。
答案 0 :(得分:44)
最终解决了问题
即便 - 虽然答案太晚了。我已经研究了很多来完成任务以获得正确的结果,但却无法完成。所以我终于解决了我们正在搜索的问题,并向谷歌搜索者提供了这个答案,以节省搜索时间。
以下代码的确认
在文本发生变化时,在EditText
中放置千位分隔符。
在按下句点(。)时自动添加0.
。
在Beginning忽略0
输入。
只需复制以下内容即可 名为
的类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;
}
}
}
在EditText
上使用此课程如下
editText.addTextChangedListener(new NumberTextWatcherForThousand(editText));
将输入视为普通双文
使用同一类的trimCommaOfString
方法
NumberTextWatcherForThousand.trimCommaOfString(editText.getText().toString())
答案 1 :(得分:35)
您可以在TextWatcher
中使用String.format()
。 格式说明符中的逗号可以解决问题。
这不适用于浮点输入。并注意不要使用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
}
答案 2 :(得分:24)
public static String doubleToStringNoDecimal(double d) {
DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US);;
formatter .applyPattern("#,###");
return formatter.format(d);
}
答案 3 :(得分:5)
此sample app清楚地解构格式化数字。
要总结上述链接,请使用TextWatcher
并使用afterTextChanged()
方法格式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);
}
答案 4 :(得分:2)
此解决方案比其他答案有一些优势。例如,即使编辑了数字的开头或中间,它也会保持用户的光标位置。 其他解决方案始终将光标跳到数字的末尾。它处理小数和整数,以及使用除.
以外的字符作为小数分隔符的区域设置,以及用于千位分组分隔符的,
。
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 == ',') {
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) {
}
}
然后在xml:
<EditText
android:id="@+id/myNumberField"
android:digits=",.0123456789"
android:inputType="numberDecimal"
.../>
最后注册观察者:
findViewById(R.id.myNumberField).addTextChangedListener(
SeparateThousands(groupingSeparator, decimalSeparator))
要处理。 vs,在不同的语言环境中使用groupingSeparator和decimalSeparator,它们可以来自DecimalFormatSymbols或本地化字符串。
答案 5 :(得分:2)
我知道我参加聚会很晚,但对未来的用户来说可能非常有用。我的回答是Shree Krishna答案的延伸。
改进:
subprocess.check_call("cp -rv ./src/CopyPasteIntoBuildDir/* ./build-root/src/", shell=True, executable="/bin/bash")
。Locale
方法改进了代码的整体质量。代码:
getDecimalFormattedString
答案 6 :(得分:1)
你可以在你的程序中以多种方式使用这段代码,你给它一个字符串,它将每三个与右边分开,并在那里放置空间。
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()
你可以稍微改变它并使用它ontextchangelistener。 祝你好运
答案 7 :(得分:1)
这是我的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();
}
}
}
是强>
<.ThousandNumberEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
答案 8 :(得分:1)
您可以使用此方法:
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) {
}
});
要获取原始文本,请使用此:
String input = myEditText.getText().toString();
input = input.replace(",", "");
答案 9 :(得分:0)
由于我有同样的问题,我决定找到解决方案
在下面找到我的功能,希望它可以帮助人们找到解决方案
securityDeposit.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
// TODO Auto-generated method stub
}
@Override
public void beforeTextChanged(CharSequence s, int start,
int before, int count) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
if (s.toString().trim().length() > 0) {
int rentValue = Integer.parseInt(s.toString()
.replaceAll(",", ""));
StringBuffer rentVal = new StringBuffer();
if (rentValue > 10000000) {
s.clear();
s.append("10,000,000");
} else {
if (s.length() == 4) {
char x[] = s.toString().toCharArray();
char y[] = new char[x.length + 1];
for (int z = 0; z < y.length; z++) {
if (z == 1) {
y[1] = ',';
} else {
if (z == 0)
y[z] = x[z];
else {
y[z] = x[z - 1];
}
}
}
for (int z = 0; z < y.length; z++) {
rentVal = rentVal.append(y[z]);
}
s.clear();
s.append(rentVal);
}
}
}
}
});
答案 10 :(得分:0)
我只是想放comma
,这对我有用:
String.format("%,.2f", myValue);
答案 11 :(得分:0)
此处的答案缺少一种处理实际用户输入的方法,例如删除字符或复制和粘贴。这是一个EditText字段。如果要添加格式,则需要支持编辑该格式的值。
根据您的用例,此实现仍然存在缺陷。我不在乎十进制值,并假设我只会处理整数。在此页面上,如何处理以及如何处理实际的国际化已经足够了,我将其留给读者练习。如果需要这样做,添加“。”应该不会太困难。正则表达式保留小数;您只需注意承认数字字符串仍然具有非数字字符即可。
旨在将其用于多个活动。对其进行一次新建,为其提供编辑文本和数据模型,然后将其忽略。如果不需要模型绑定,可以将其删除。
public class EditNumberFormatter implements TextWatcher {
private EditText watched;
private Object model;
private Field field;
private IEditNumberFormatterListener listener;
private ActiveEdit activeEdit;
/**
* Binds an EditText to a data model field (Such as a room entity's public variable)
* Whenever the edit text is changed, the text is formatted to the local numerical format.
*
* Handles copy/paste/backspace/select&delete/typing
*
* @param model An object with a public field to bind to
* @param fieldName A field defined on the object
* @param watched The edit text to watch for changes
* @param listener Another object that wants to know after changes & formatting are done.
*/
public EditNumberFormatter(Object model, String fieldName, EditText watched, IEditNumberFormatterListener listener) {
this.model = model;
this.watched = watched;
this.listener = listener;
try {
field = model.getClass().getDeclaredField(fieldName);
} catch(Exception e) { }
watched.addTextChangedListener(this);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
activeEdit = new ActiveEdit(s.toString(), start, count);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
activeEdit.recordChangedText(s.toString(),count);
}
@Override
public void afterTextChanged(Editable s) {
this.watched.removeTextChangedListener(this);
activeEdit.processEdit(); // Override the user's edit of the formatted string with what the user intended to do to the numeral.
watched.setText(activeEdit.getCurrentFormattedString());
watched.setSelection(activeEdit.getCursorPosition());
updateDataModel(activeEdit.getCurrentRawValue());
listener.FormatUpdated(watched.getId(), activeEdit.getCurrentRawValue(), activeEdit.getCurrentFormattedString());
this.watched.addTextChangedListener(this);
}
private void updateDataModel(int rawValue) {
try {
field.set(model, rawValue);
} catch (IllegalAccessException e) { }
}
/**
* Tracks the active editing of an EditText formatted for integer input
*/
private class ActiveEdit {
private String priorFormattedString;
private String currentFormattedString;
private String currentNumericalString;
private int currentRawValue;
private boolean removal;
private boolean addition;
private int changeStart;
private int removedCount;
private int additionCount;
private int numeralCountBeforeSelection;
private int numeralCountAdded;
private int numeralCountRemoved;
/**
* Call in beforeEdit to begin recording changes
*
* @param beforeEdit string before edit began
* @param start start position of edit
* @param removed number of characters removed
*/
public ActiveEdit(String beforeEdit, int start, int removed) {
removal = (removed > 0);
priorFormattedString = beforeEdit;
changeStart = start;
removedCount = removed;
numeralCountBeforeSelection = countNumerals(priorFormattedString.substring(0, changeStart));
numeralCountRemoved = countNumerals(priorFormattedString.substring(changeStart, changeStart + removedCount));
}
/**
* Call in onTextChanged to record new text and how many characters were added after changeStart
*
* @param afterEdit new string after user input
* @param added how many characters were added (same start position as before)
*/
public void recordChangedText(String afterEdit, int added) {
addition = (added > 0);
additionCount = added;
numeralCountAdded = countNumerals(afterEdit.substring(changeStart, changeStart + additionCount));
currentNumericalString = afterEdit.replaceAll("[^0-9]", "");
}
/**
* Re-process the edit for our particular formatting needs.
*/
public void processEdit() {
forceRemovalPastFormatting();
finalizeEdit();
}
/**
* @return Integer value of the field after an edit.
*/
public int getCurrentRawValue() {
return currentRawValue;
}
/**
* @return Formatted number after an edit.
*/
public String getCurrentFormattedString() {
return currentFormattedString;
}
/**
* @return Cursor position after an edit
*/
public int getCursorPosition() {
int numeralPosition = numeralCountBeforeSelection + numeralCountAdded;
return positionAfterNumeralN(currentFormattedString,numeralPosition);
}
/**
* If a user deletes a value, but no numerals are deleted, then delete the numeral proceeding
* their cursor. Otherwise, we'll just add back the formatting character.
*
* Assumes formatting uses a single character and not multiple formatting characters in a row.
*/
private void forceRemovalPastFormatting() {
if (removal && (!addition) && (numeralCountRemoved == 0)) {
String before = currentNumericalString.substring(0, numeralCountBeforeSelection - 1);
String after = currentNumericalString.substring(numeralCountBeforeSelection);
currentNumericalString = before + after;
numeralCountRemoved++;
numeralCountBeforeSelection--;
}
}
/**
* Determine the result of the edit, including new display value and raw value
*/
private void finalizeEdit() {
currentFormattedString = "";
currentRawValue = 0;
if (currentNumericalString.length() == 0) {
return; // There is no entry now.
}
try {
currentRawValue = Integer.parseInt(currentNumericalString);
} catch (NumberFormatException nfe) {
abortEdit(); // Value is not an integer, return to previous state.
return;
}
currentFormattedString = String.format("%,d", currentRawValue);
}
/**
* Current text, same as the old text.
*/
private void abortEdit() {
currentFormattedString = priorFormattedString;
currentNumericalString = currentFormattedString.replaceAll("[^0-9]", "");
numeralCountRemoved = 0;
numeralCountAdded = 0;
try {
currentRawValue = Integer.parseInt(currentNumericalString);
} catch (Exception e) { currentRawValue = 0; }
}
/**
* Determine how many numerical characters exist in a string
* @param s
* @return the number of numerical characters in the string
*/
private int countNumerals(String s) {
String newString = s.replaceAll("[^0-9]", "");
return newString.length();
}
/**
* Determine how to place a cursor after the Nth Numeral in a formatted string.
* @param s - Formatted string
* @param n - The position of the cursor should follow the "Nth" number in the string
* @return the position of the nth character in a formatted string
*/
private int positionAfterNumeralN(String s, int n) {
int numeralsFound = 0;
if (n == 0) {
return 0;
}
for (int i = 0; i < s.length(); i++) {
if(s.substring(i,i+1).matches("[0-9]")) {
if(++numeralsFound == n) {
return i + 1;
}
}
}
return s.length();
}
}
}
总的来说,它是:
它也可以很好地处理完全删除的输入,整数溢出和错误输入等极端情况。
答案 12 :(得分:0)
在这里,我已经测试了我的应用程序代码。文本观察程序如何以货币千(湖货币)添加逗号。
private TextWatcher textWatcherAmount = 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 initial = s.toString();
if (inputEdtHawalaRate == null) return;
if (!TextUtils.isEmpty(initial)) {
initial = initial.replace(",", "");
NumberFormat formatter = new DecimalFormat("##,##,###");
inputEdtHawalaRate.removeTextChangedListener(this);
double myNumber = Double.parseDouble(initial);
String processed = formatter.format(myNumber);
//Assign processed text
inputEdtHawalaRate.setText(processed);
try {
inputEdtHawalaRate.setSelection(processed.length());
} catch (Exception e) {
e.printStackTrace();
}
//Give back the listener
inputEdtHawalaRate.addTextChangedListener(this);
}
}
@Override
public void afterTextChanged(Editable s) {
}
};
if (inputEdtHawalaRate != null) {
inputEdtHawalaRate.addTextChangedListener(textWatcherAmount);
}
//在双精度变量上获取金额(在textwatcher上,editetxt值获取)。
String amount = Objects.requireNonNull(inputEdtHawalaRate.getText()).toString().trim();
double hawalaAmount = 0.0;
String[] a = amount.split(",");
finalAmount = TextUtils.join("", a);
hawalaAmount = Double.parseDouble(finalAmount);
答案 13 :(得分:0)
您可以使用自定义 TextInputEditText :
public class NumberTextInputEditText extends TextInputEditText {
public NumberTextInputEditText(@NonNull Context context) {
super(context);
}
public NumberTextInputEditText(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public NumberTextInputEditText(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
addTextChangedListener(textWatcher);
}
public String formatNumber(double number) {
DecimalFormat decimalFormat = new DecimalFormat("#,###");
return decimalFormat.format(number);
}
public TextWatcher textWatcher = new TextWatcher() {
@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) {
removeTextChangedListener(this);
String text = getText().toString();
String format = "";
if (!TextUtils.isEmpty(text)) {
try {
format = formatNumber(Double.parseDouble(new BigDecimal(text.replaceAll(",", "")).toString()));
} catch (NumberFormatException e) {
format = "";
}
setText(format);
setSelection(format.length());
}
addTextChangedListener(this);
}
};}
只需像布局中的视图一样使用它:
<com.your.package.name.NumberTextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>