有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java正则表达式,允许带有numberdCimal的$符号

我在EditText上设置了一个InputFilter来输入金额

InputFilter filter = new InputFilter() {
        final int maxDigitsBeforeDecimalPoint = 5;
        final int maxDigitsAfterDecimalPoint = 2;
        @Override
        public CharSequence filter(CharSequence source, int start, int end,
                                   Spanned dest, int dstart, int dend) {
            StringBuilder builder = new StringBuilder(dest);
            builder.replace(dstart, dend, source
                    .subSequence(start, end).toString());
            if (!builder.toString().matches(
                    "(([1-9]{1})([0-9]{0," + (maxDigitsBeforeDecimalPoint - 1) + "})?)?(\\.[0-9]{0," + maxDigitsAfterDecimalPoint + "})?"
            )) {
                if (source.length() == 0)
                    return dest.subSequence(dstart, dend);
                return "";
            }
            return null;
        }
    };

这很好用。现在我需要插入一个$符号作为amount的前缀。所以我需要修改regx。我尝试的是:-

"(([${0,1}][1-9]{1})([0-9]{0," + (maxDigitsBeforeDecimalPoint - 1) + "})?)?(\\.[0-9]{0," + maxDigitsAfterDecimalPoint + "})?"

但是当我把TextWatcher放进去时,它不允许我删除最后一个数字。 如果EditText持有$3,则不会删除它

edtAmount.addTextChangedListener(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) {
            String input = editable.toString();
            if (TextUtils.isEmpty(input))
                return;
            if (input.equals("$")) {
                edtAmount.setText("");
                return;
            }
            if(!input.startsWith("$")){
                edtAmount.setText("$" + input);
                edtAmount.setSelection(edtAmount.getText().toString().length());
            }
        }
    });

请告诉我罪魁祸首是什么。我不擅长正则表达式


共 (2) 个答案

  1. # 1 楼答案

    您可以使用以下库来实现此目的

    https://github.com/BlacKCaT27/CurrencyEditText

    You can use any type of currency with this

    当前编辑文本

    CurrencyEditText是Android的EditText视图对象的扩展。它是一个模块,设计用于在使用EditText字段从用户收集货币信息时提供易用性

    CurrencyEditText设计用于所有符合ISO-3166标准的地区(应包括Android ships将提供的所有地区)

    如果发现某个区域设置导致了问题,请在问题跟踪器中打开问题

    更新的答案

    如果上述链接不起作用,请使用以下代码-

    import android.content.Context;
    import android.content.res.TypedArray;
    import android.os.Build;
    import android.text.Editable;
    import android.text.InputType;
    import android.text.TextWatcher;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.widget.EditText;
    
    import java.text.DecimalFormat;
    import java.text.DecimalFormatSymbols;
    import java.text.ParseException;
    import java.util.Currency;
    import java.util.Locale;
    
    
    public class CurrencyEditText extends EditText {
       private char mGroupDivider;
       private char mMonetaryDivider;
       private String mLocale = "";
       private boolean mShowSymbol;
    
       private char groupDivider;
       private char monetaryDivider;
    
       private Locale locale;
       private DecimalFormat numberFormat;
    
       private int fractionDigit;
       private String currencySymbol;
    
       public CurrencyEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
    
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.currencyEditText, 0, 0);
    
        try {
            if (a.getString(R.styleable.currencyEditText_groupDivider) != null) {
                this.mGroupDivider = a.getString(R.styleable.currencyEditText_groupDivider).charAt(0);
                this.groupDivider = mGroupDivider;
            }
    
            if (a.getString(R.styleable.currencyEditText_monetaryDivider) != null) {
                this.mMonetaryDivider = a.getString(R.styleable.currencyEditText_monetaryDivider).charAt(0);
                this.monetaryDivider = mMonetaryDivider;
            }
    
            if (a.getString(R.styleable.currencyEditText_locale) == null)
                this.locale = getDefaultLocale();
            else this.mLocale = a.getString(R.styleable.currencyEditText_locale);
    
            if (a.getString(R.styleable.currencyEditText_showSymbol) != null)
                this.mShowSymbol = a.getBoolean(R.styleable.currencyEditText_showSymbol, false);
    
            if (mLocale.equals("")) {
                locale = getDefaultLocale();
            } else {
                if (mLocale.contains("-"))
                    mLocale = mLocale.replace("-", "_");
    
                String[] l = mLocale.split("_");
                if (l.length > 1) {
                    locale = new Locale(l[0], l[1]);
                } else {
                    locale = new Locale("", mLocale);
                }
            }
    
            initSettings();
        } finally {
            a.recycle();
        }
    
        this.addTextChangedListener(onTextChangeListener);
    }
    
    /***
     * If user does not provide a valid locale it throws IllegalArgumentException.
     * 
     * If throws an IllegalArgumentException the locale sets to default locale
     */
    private void initSettings() {
        boolean success = false;
        while (!success) {
            try {
                fractionDigit = Currency.getInstance(locale).getDefaultFractionDigits();
    
                DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
                if (mGroupDivider > 0)
                    symbols.setGroupingSeparator(mGroupDivider);
                groupDivider = symbols.getGroupingSeparator();
    
                if (mMonetaryDivider > 0)
                    symbols.setMonetaryDecimalSeparator(mMonetaryDivider);
                monetaryDivider = symbols.getMonetaryDecimalSeparator();
    
                currencySymbol = symbols.getCurrencySymbol();
    
                DecimalFormat df = (DecimalFormat) DecimalFormat.getCurrencyInstance(locale);
                numberFormat = new DecimalFormat(df.toPattern(), symbols);
    
                success = true;
            } catch (IllegalArgumentException e) {
                Log.e(getClass().getCanonicalName(), e.getMessage());
                locale = getDefaultLocale();
            }
        }
    }
    
    private Locale getDefaultLocale() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
            return getContext().getResources().getConfiguration().getLocales().get(0);
        else
            return getContext().getResources().getConfiguration().locale;
    }
    
    /***
     *It resets text currently displayed If user changes separators or locale etc.
     */
    private void resetText() {
        String s = getText().toString();
        if (s.isEmpty()) {
            initSettings();
            return;
        }
    
        s = s.replace(groupDivider, '\u0020').replace(monetaryDivider, '\u0020')
                .replace(".", "").replace(" ", "")
                .replace(currencySymbol, "").trim();
        try {
            initSettings();
            s = format(s);
            removeTextChangedListener(onTextChangeListener);
            setText(s);
            setSelection(s.length());
            addTextChangedListener(onTextChangeListener);
        } catch (ParseException e) {
            Log.e(getClass().getCanonicalName(), e.getMessage());
        }
    }
    
    private TextWatcher onTextChangeListener = 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) {
            if (s.length() == 0)
                return;
    
            removeTextChangedListener(this);
    
            /***
             * Clear input to get clean text before format
             * '\u0020' is empty character
             */
            String text = s.toString();
            text = text.replace(groupDivider, '\u0020').replace(monetaryDivider, '\u0020')
                    .replace(".", "").replace(" ", "")
                    .replace(currencySymbol, "").trim();
            try {
                text = format(text);
            } catch (ParseException e) {
                Log.e(getClass().getCanonicalName(), e.getMessage());
            }
    
            setText(text);
            setSelection(text.length());
    
            addTextChangedListener(this);
        }
    
        @Override
        public void afterTextChanged(Editable s) {
    
        }
    };
    
    private String format(String text) throws ParseException {
        if (mShowSymbol)
            return numberFormat.format(Double.parseDouble(text) / Math.pow(10, fractionDigit));
        else
            return numberFormat.format(Double.parseDouble(text) / Math.pow(10, fractionDigit)).replace(currencySymbol, "");
    }
    
    /***
     * returns the decimal separator for current locale
     * for example; input value 1,234.56
     *              returns ','
     *
     * @return decimal separator char
     */
    public char getGroupDivider() {
        return groupDivider;
    }
    
    /***
     * sets how to divide decimal value and fractions
     * for example; If you want formatting like this
     *              for input value 1,234.56
     *              set ','
     * @param groupDivider char
     */
    public void setGroupDivider(char groupDivider) {
        this.mGroupDivider = groupDivider;
        resetText();
    }
    
    /***
     * returns the monetary separator for current locale
     * for example; input value 1,234.56
     *              returns '.'
     *
     * @return monetary separator char
     */
    public char getMonetaryDivider() {
        return monetaryDivider;
    }
    
    /***
     * sets how to divide decimal value and fractions
     * for example; If you want formatting like this
     *              for input value 1,234.56
     *              set '.'
     * @param monetaryDivider char
     */
    public void setMonetaryDivider(char monetaryDivider) {
        this.mMonetaryDivider = monetaryDivider;
        resetText();
    }
    
    /***
     *
     * @return current locale
     */
    public Locale getLocale() {
        return locale;
    }
    
    /***
     * Sets locale which desired currency format
     *
     * @param locale
     */
    public void setLocale(Locale locale) {
        this.locale = locale;
        resetText();
    }
    
    /**
     *
     * @return true if currency symbol of current locale is showing
     */
    public boolean showSymbol() {
        return this.mShowSymbol;
    }
    
    /***
     * Sets if currency symbol of current locale shows
     *
     * @param showSymbol
     */
    public void showSymbol(boolean showSymbol) {
        this.mShowSymbol = showSymbol;
        resetText();
    }
    
    /**
     *
     *  @return double value for current text
     */
    public double getCurrencyDouble() throws ParseException {
        String text = getText().toString();
        text = text.replace(groupDivider, '\u0020').replace(monetaryDivider, '\u0020')
                .replace(".", "").replace(" ", "")
                .replace(currencySymbol, "").trim();
    
        if (showSymbol())
            return Double.parseDouble(text.replace(currencySymbol, "")) / Math.pow(10, fractionDigit);
        else return Double.parseDouble(text) / Math.pow(10, fractionDigit);
    }
    
    /**
     *
     *  @return String value for current text
     */
    public String getCurrencyText() throws ParseException {
        if (showSymbol())
            return getText().toString().replace(currencySymbol, "");
    }
    

    }

    此文件还需要属性。xml将此文件放在values文件夹中

      <?xml version="1.0" encoding="utf-8"?>
      <resources>
      <declare-styleable name="currencyEditText">
         <attr name="groupDivider" format="string" />
         <attr name="monetaryDivider" format="string" />
         <attr name="locale" format="string" />
         <attr name="showSymbol" format="boolean" />
     </declare-styleable>
     </resources>
    

    现在您可以使用此编辑文本

    <CurrencyEditText
        android:id="@+id/edt_currency"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="numberDecimal"
        android:textColor="@android:color/black"
        app:groupDivider="."
        app:monetaryDivider=","
        app:locale="en_US"
        app:showSymbol="true" />
    

    希望这将满足您的要求,如果没有,您可以根据需要编辑此代码

  2. # 2 楼答案

    [$]?放在最左边起作用了。因此,最终正则表达式将如下所示:

    "[$]?(([1-9]{1})([0-9]{0," + (maxDigitsBeforeDecimalPoint - 1) + "})?)?(\.[0-9]{0," + maxDigitsAfterDecimalPoint + "})?"

    谢谢大家