正则表达式允许带数字的$符号

时间:2018-09-20 11:10:22

标签: java android regex

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

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());
            }
        }
    });

请让我知道这里的罪魁祸首。我对RegEx不好。

2 个答案:

答案 0 :(得分:0)

将{{1}}放到最左边即可。所以最终的RegEx看起来像:-

  

“ [$]?(([[1-9] {1})([0-9] {0,” +(maxDigitsBeforeDecimalPoint-1)+“})?)?(\。[0-9] {0,“ + maxDigitsAfterDecimalPoint +”})?“

谢谢大家。

答案 1 :(得分:-1)

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

https://github.com/BlacKCaT27/CurrencyEditText

You can use any type of currency with this

CurrencyEditText

CurrencyEditText是Android的EditText视图对象的扩展。该模块旨在在使用EditText字段从用户收集货币信息时提供易用性。

CurrencyEditText旨在与所有符合ISO-3166的语言环境一起使用(其中应包括Android船舶将提供的所有语言环境)。

如果您发现某个区域设置引起问题,请在问题跟踪器中打开一个问题。

更新的答案

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

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, "");
}

}

此文件还需要attrs.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>

现在您可以使用此edittext

<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" />

希望这可以满足您的要求,否则您可以根据要求编辑此代码。