文本更改时将数字转换为货币格式

Posted

技术标签:

【中文标题】文本更改时将数字转换为货币格式【英文标题】:converting numbers to currency format when text changes 【发布时间】:2017-12-05 08:28:31 【问题描述】:

我将RxTextView.textChanges 用于EditText,当用户输入EditText 的更改值以将数字转换为货币格式,如下所示:

1,000

但我看不到任何将数字转换为货币格式

我正在使用来自:NumberFormat.getNumberInstance(Locale.US).format(productPrice);

我的代码如下:

Observable<CharSequence> observableDiscountPrice = RxTextView.textChanges(discountPriceEdittext);
        observableDiscountPrice.map(new Function<CharSequence, Boolean>() 
            @Override
            public Boolean apply(@io.reactivex.annotations.NonNull CharSequence charSequence) throws Exception 
                try 
                    if (charSequence.length() > 0) 
                        String pPrice = NumberFormat.getNumberInstance(Locale.US).format(charSequence.toString());
                        originalPriceEdittext.setText(String.valueOf(pPrice));
                        return true;
                     else 
                        return false;
                    
                 catch (Exception e) 
                    return true;
                
            
        ).subscribe(new Subject<Boolean>() 
            @Override
            public boolean hasObservers() 
                return false;
            

            @Override
            public boolean hasThrowable() 
                return false;
            

            @Override
            public boolean hasComplete() 
                return false;
            

            @Override
            public Throwable getThrowable() 
                return null;
            

            @Override
            protected void subscribeActual(Observer<? super Boolean> observer) 

            

            @Override
            public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) 

            

            @Override
            public void onNext(@io.reactivex.annotations.NonNull Boolean aBoolean) 
            

            @Override
            public void onError(@io.reactivex.annotations.NonNull Throwable e) 

            

            @Override
            public void onComplete() 

            
        );

【问题讨论】:

你能检查你的 NumberFormat 的导入吗? 【参考方案1】:

使用这个 TextWatcher 类:

public class NumberTextWatcherWithSeperator implements TextWatcher 

private EditText editText;


public NumberTextWatcherWithSeperator(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.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);
     catch (Exception ex) 
        ex.printStackTrace();
        editText.addTextChangedListener(this);
    


private 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++;
    




yourEditText.addTextChangedListener(new NumberTextWatcherWithSeperator(yourEditText));

【讨论】:

@Alireza Noorali。此类在经常设备上存在错误。 @JoJoRoid:我已经在我的应用程序中使用了这个类,而且我的 Fabric crashlytics 报告中从来没有发生过一次崩溃。你试过这门课吗? 您的代码运行良好,但如何将小数位限制为 2【参考方案2】:

看看https://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html

    DecimalFormat myFormatter = new DecimalFormat("###,###.###");
    String output = myFormatter.format(156456.673);
    System.out.println(156456.673 + " " + "###,###.###" + " " + output);

// I/System.out: 156456.673 ###,###.### 156,456.673

【讨论】:

@Milos Lulic。我对此进行了测试,但这种方式在 textChanges 中有错误。【参考方案3】:

我正在使用这个观察者做同样的事情:

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

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

    public class CurrencyTextWatcher implements TextWatcher 

    private EditText ed;
    private String lastText;
    private boolean bDel = false;
    private boolean bInsert = false;
    private int pos;

    public CurrencyTextWatcher(EditText ed) 
        this.ed = ed;
    

    public static String getStringWithSeparator(long value) 
        DecimalFormat formatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);
        String f = formatter.format(value);
        return f;
    

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) 
        bDel = false;
        bInsert = false;
        if (before == 1 && count == 0) 
            bDel = true;
            pos = start;
         else if (before == 0 && count == 1) 
            bInsert = true;
            pos = start;
        
    

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) 
        lastText = s.toString();
    

    @Override
    public void afterTextChanged(Editable s) 
        ed.removeTextChangedListener(this);
        StringBuilder sb = new StringBuilder();
        String text = s.toString();
        for (int i = 0; i < text.length(); i++) 
            if ((text.charAt(i) >= 0x30 && text.charAt(i) <= 0x39) || text.charAt(i) == '.' || text.charAt(i) == ',')
                sb.append(text.charAt(i));
        
        if (!sb.toString().equals(s.toString())) 
            bDel = bInsert = false;
        
        String newText = getFormattedString(sb.toString());
        s.clear();
        s.append(newText);
        ed.addTextChangedListener(this);

        if (bDel) 
            int idx = pos;
            if (lastText.length() - 1 > newText.length())
                idx--; 
            if (idx < 0)
                idx = 0;
            ed.setSelection(idx);
         else if (bInsert) 
            int idx = pos + 1;
            if (lastText.length() + 1 < newText.length())
                idx++; 
            if (idx > newText.length())
                idx = newText.length();
            ed.setSelection(idx);
        
    

    private String getFormattedString(String text) 
        String res = "";
        try 
            String temp = text.replace(",", "");
            long part1;
            String part2 = "";
            int dotIndex = temp.indexOf(".");
            if (dotIndex >= 0) 
                part1 = Long.parseLong(temp.substring(0, dotIndex));
                if (dotIndex + 1 <= temp.length()) 
                    part2 = temp.substring(dotIndex + 1).trim().replace(".", "").replace(",", "");
                
             else
                part1 = Long.parseLong(temp);

            res = getStringWithSeparator(part1);
            if (part2.length() > 0)
                res += "." + part2;
            else if (dotIndex >= 0)
                res += ".";
         catch (Exception ex) 
            ex.printStackTrace();
        
        return res;
    

【讨论】:

【参考方案4】:

如果你想和美元符号

    fun multiply_two_numbers() 

    val x = etValOne.text.toString()
    val y = etValTwo.text.toString()
    val c =  x.toDouble().times(y.toDouble())
    //val c = (x.toDouble() * y.toDouble())
    val df = DecimalFormat("$ "+"0.00")
    df.roundingMode = RoundingMode.CEILING
    df.format(c)
    etANS.setText(df.format(c))

【讨论】:

以上是关于文本更改时将数字转换为货币格式的主要内容,如果未能解决你的问题,请参考以下文章

将数字字符串转换为不同的区域格式

在应用程序脚本中将数字转换为货币?

ASP中有啥函数把文本型值转换为数值型值?

在输入框中输入时将整数转换为货币格式

如何把文本转化为数字

将货币字符串转换为数字 Drupal Views / PHP