我有一个editText,起始值是0.00美元.按1时,它变为$ 0.01.按4,它达到$ 0.14.按8,$ 1.48.按退格键,0.14美元等
这是有效的,问题是,如果有人手动定位光标,格式化中会出现问题.如果他们要删除小数,它就不会回来.如果他们将光标放在小数前面并输入2,它将显示$ 02.00而不是$ 2.00.例如,如果他们试图删除$,它将删除一个数字.
这是我正在使用的代码,我很感激任何建议.
mEditPrice.setRawInputType(Configuration.KEYBOARD_12KEY);
public void priceClick(View view) {
mEditPrice.addTextChangedListener(new TextWatcher(){
DecimalFormat dec = new DecimalFormat("0.00");
@Override
public void afterTextChanged(Editable arg0) {
}
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if(!s.toString().matches("^\\$(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$"))
{
String userInput= ""+s.toString().replaceAll("[^\\d]", "");
if (userInput.length() > 0) {
Float in=Float.parseFloat(userInput);
float percen = in/100;
mEditPrice.setText("$"+dec.format(percen));
mEditPrice.setSelection(mEditPrice.getText().length());
}
}
}
});
Run Code Online (Sandbox Code Playgroud)
Gui*_*ira 141
我测试了你的方法,但是当我使用大数字时它失败了...我创建了这个:
private String current = "";
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(!s.toString().equals(current)){
[your_edittext].removeTextChangedListener(this);
String cleanString = s.toString().replaceAll("[$,.]", "");
double parsed = Double.parseDouble(cleanString);
String formatted = NumberFormat.getCurrencyInstance().format((parsed/100));
current = formatted;
[your_edittext].setText(formatted);
[your_edittext].setSelection(formatted.length());
[your_edittext].addTextChangedListener(this);
}
}
Run Code Online (Sandbox Code Playgroud)
Tod*_*ddH 25
基于上面的一些答案,我创建了一个MoneyTextWatcher,你可以使用如下:
priceEditText.addTextChangedListener(new MoneyTextWatcher(priceEditText));
Run Code Online (Sandbox Code Playgroud)
这是班级:
public class MoneyTextWatcher implements TextWatcher {
private final WeakReference<EditText> editTextWeakReference;
public MoneyTextWatcher(EditText editText) {
editTextWeakReference = new WeakReference<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 editable) {
EditText editText = editTextWeakReference.get();
if (editText == null) return;
String s = editable.toString();
if (s.isEmpty()) return;
editText.removeTextChangedListener(this);
String cleanString = s.replaceAll("[$,.]", "");
BigDecimal parsed = new BigDecimal(cleanString).setScale(2, BigDecimal.ROUND_FLOOR).divide(new BigDecimal(100), BigDecimal.ROUND_FLOOR);
String formatted = NumberFormat.getCurrencyInstance().format(parsed);
editText.setText(formatted);
editText.setSelection(formatted.length());
editText.addTextChangedListener(this);
}
}
Run Code Online (Sandbox Code Playgroud)
Pha*_*inh 16
这是我的习惯 CurrencyEditText
import android.content.Context;import android.graphics.Rect;import android.text.Editable;import android.text.InputFilter;import android.text.InputType;import android.text.TextWatcher;
import android.util.AttributeSet;import android.widget.EditText;import java.math.BigDecimal;import java.math.RoundingMode;
import java.text.DecimalFormat;import java.text.DecimalFormatSymbols;
import java.util.Locale;
/**
* Some note <br/>
* <li>Always use locale US instead of default to make DecimalFormat work well in all language</li>
*/
public class CurrencyEditText extends android.support.v7.widget.AppCompatEditText {
private static String prefix = "VND ";
private static final int MAX_LENGTH = 20;
private static final int MAX_DECIMAL = 3;
private CurrencyTextWatcher currencyTextWatcher = new CurrencyTextWatcher(this, prefix);
public CurrencyEditText(Context context) {
this(context, null);
}
public CurrencyEditText(Context context, AttributeSet attrs) {
this(context, attrs, android.support.v7.appcompat.R.attr.editTextStyle);
}
public CurrencyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
this.setHint(prefix);
this.setFilters(new InputFilter[] { new InputFilter.LengthFilter(MAX_LENGTH) });
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if (focused) {
this.addTextChangedListener(currencyTextWatcher);
} else {
this.removeTextChangedListener(currencyTextWatcher);
}
handleCaseCurrencyEmpty(focused);
}
/**
* When currency empty <br/>
* + When focus EditText, set the default text = prefix (ex: VND) <br/>
* + When EditText lose focus, set the default text = "", EditText will display hint (ex:VND)
*/
private void handleCaseCurrencyEmpty(boolean focused) {
if (focused) {
if (getText().toString().isEmpty()) {
setText(prefix);
}
} else {
if (getText().toString().equals(prefix)) {
setText("");
}
}
}
private static class CurrencyTextWatcher implements TextWatcher {
private final EditText editText;
private String previousCleanString;
private String prefix;
CurrencyTextWatcher(EditText editText, String prefix) {
this.editText = editText;
this.prefix = prefix;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// do nothing
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// do nothing
}
@Override
public void afterTextChanged(Editable editable) {
String str = editable.toString();
if (str.length() < prefix.length()) {
editText.setText(prefix);
editText.setSelection(prefix.length());
return;
}
if (str.equals(prefix)) {
return;
}
// cleanString this the string which not contain prefix and ,
String cleanString = str.replace(prefix, "").replaceAll("[,]", "");
// for prevent afterTextChanged recursive call
if (cleanString.equals(previousCleanString) || cleanString.isEmpty()) {
return;
}
previousCleanString = cleanString;
String formattedString;
if (cleanString.contains(".")) {
formattedString = formatDecimal(cleanString);
} else {
formattedString = formatInteger(cleanString);
}
editText.removeTextChangedListener(this); // Remove listener
editText.setText(formattedString);
handleSelection();
editText.addTextChangedListener(this); // Add back the listener
}
private String formatInteger(String str) {
BigDecimal parsed = new BigDecimal(str);
DecimalFormat formatter =
new DecimalFormat(prefix + "#,###", new DecimalFormatSymbols(Locale.US));
return formatter.format(parsed);
}
private String formatDecimal(String str) {
if (str.equals(".")) {
return prefix + ".";
}
BigDecimal parsed = new BigDecimal(str);
// example pattern VND #,###.00
DecimalFormat formatter = new DecimalFormat(prefix + "#,###." + getDecimalPattern(str),
new DecimalFormatSymbols(Locale.US));
formatter.setRoundingMode(RoundingMode.DOWN);
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() - str.indexOf(".") - 1;
StringBuilder decimalPattern = new StringBuilder();
for (int i = 0; i < decimalCount && i < MAX_DECIMAL; i++) {
decimalPattern.append("0");
}
return decimalPattern.toString();
}
private void handleSelection() {
if (editText.getText().length() <= MAX_LENGTH) {
editText.setSelection(editText.getText().length());
} else {
editText.setSelection(MAX_LENGTH);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在XML中使用它
<...CurrencyEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
Run Code Online (Sandbox Code Playgroud)
您应该在下面编辑2常量以适合您的项目
private static String prefix = "VND ";
private static final int MAX_DECIMAL = 3;
Run Code Online (Sandbox Code Playgroud)
sfr*_*ini 12
实际上,之前提供的解决方案不起作用.如果要输入100.00,则不起作用.
更换:
double parsed = Double.parseDouble(cleanString);
String formato = NumberFormat.getCurrencyInstance().format((parsed/100));
Run Code Online (Sandbox Code Playgroud)
附:
BigDecimal parsed = new BigDecimal(cleanString).setScale(2,BigDecimal.ROUND_FLOOR).divide(new BigDecimal(100),BigDecimal.ROUND_FLOOR);
String formato = NumberFormat.getCurrencyInstance().format(parsed);
Run Code Online (Sandbox Code Playgroud)
我必须说我对我的代码进行了一些修改.问题是你应该使用BigDecimal
我使用 Nathan Leigh 引用的实现以及 Kayvan N 和 user2582318 建议的正则表达式来删除除数字之外的所有字符,以创建以下版本:
fun EditText.addCurrencyFormatter() {
// Reference: /sf/ask/357553101/#29993290
this.addTextChangedListener(object: TextWatcher {
private var current = ""
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (s.toString() != current) {
this@addCurrencyFormatter.removeTextChangedListener(this)
// strip off the currency symbol
// Reference for this replace regex: /sf/ask/357553101/#28005836
val cleanString = s.toString().replace("\\D".toRegex(), "")
val parsed = if (cleanString.isBlank()) 0.0 else cleanString.toDouble()
// format the double into a currency format
val formated = NumberFormat.getCurrencyInstance()
.format(parsed / 100)
current = formated
this@addCurrencyFormatter.setText(formated)
this@addCurrencyFormatter.setSelection(formated.length)
this@addCurrencyFormatter.addTextChangedListener(this)
}
}
})
}
Run Code Online (Sandbox Code Playgroud)
这是 Kotlin 中的一个扩展函数,它将 TextWatcher 添加到 EditText 的 TextChangedListener 中。
为了使用它,只需:
yourEditText = (EditText) findViewById(R.id.edit_text_your_id);
yourEditText.addCurrencyFormatter()
Run Code Online (Sandbox Code Playgroud)
我希望它有帮助。
小智 6
我使用实现TextWatcher更改类以使用Brasil货币格式并在编辑值时调整光标位置.
public class MoneyTextWatcher implements TextWatcher {
private EditText editText;
private String lastAmount = "";
private int lastCursorPosition = -1;
public MoneyTextWatcher(EditText editText) {
super();
this.editText = editText;
}
@Override
public void onTextChanged(CharSequence amount, int start, int before, int count) {
if (!amount.toString().equals(lastAmount)) {
String cleanString = clearCurrencyToNumber(amount.toString());
try {
String formattedAmount = transformToCurrency(cleanString);
editText.removeTextChangedListener(this);
editText.setText(formattedAmount);
editText.setSelection(formattedAmount.length());
editText.addTextChangedListener(this);
if (lastCursorPosition != lastAmount.length() && lastCursorPosition != -1) {
int lengthDelta = formattedAmount.length() - lastAmount.length();
int newCursorOffset = max(0, min(formattedAmount.length(), lastCursorPosition + lengthDelta));
editText.setSelection(newCursorOffset);
}
} catch (Exception e) {
//log something
}
}
}
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
String value = s.toString();
if(!value.equals("")){
String cleanString = clearCurrencyToNumber(value);
String formattedAmount = transformToCurrency(cleanString);
lastAmount = formattedAmount;
lastCursorPosition = editText.getSelectionStart();
}
}
public static String clearCurrencyToNumber(String currencyValue) {
String result = null;
if (currencyValue == null) {
result = "";
} else {
result = currencyValue.replaceAll("[(a-z)|(A-Z)|($,. )]", "");
}
return result;
}
public static boolean isCurrencyValue(String currencyValue, boolean podeSerZero) {
boolean result;
if (currencyValue == null || currencyValue.length() == 0) {
result = false;
} else {
if (!podeSerZero && currencyValue.equals("0,00")) {
result = false;
} else {
result = true;
}
}
return result;
}
public static String transformToCurrency(String value) {
double parsed = Double.parseDouble(value);
String formatted = NumberFormat.getCurrencyInstance(new Locale("pt", "BR")).format((parsed / 100));
formatted = formatted.replaceAll("[^(0-9)(.,)]", "");
return formatted;
}
}
尽管这里有很多答案,但我想分享我在这里找到的代码,因为我相信它是最强大和最干净的答案。
class CurrencyTextWatcher implements TextWatcher {
boolean mEditing;
public CurrencyTextWatcher() {
mEditing = false;
}
public synchronized void afterTextChanged(Editable s) {
if(!mEditing) {
mEditing = true;
String digits = s.toString().replaceAll("\\D", "");
NumberFormat nf = NumberFormat.getCurrencyInstance();
try{
String formatted = nf.format(Double.parseDouble(digits)/100);
s.replace(0, s.length(), formatted);
} catch (NumberFormatException nfe) {
s.clear();
}
mEditing = false;
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
public void onTextChanged(CharSequence s, int start, int before, int count) { }
}
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你。