EditText金額輸入(限制輸入金額大小和小數(shù)點(diǎn)后兩位)

EditText金額輸入(限制輸入金額大小和小數(shù)點(diǎn)后兩位)

標(biāo)簽(空格分隔): Android開發(fā)


Android中控制EditText輸入內(nèi)容、長(zhǎng)度的方法有三種

  • 方案一:

    • 通過監(jiān)聽EditText的addTextChangedListener方法
  • 方案二:通過setFilter()方法設(shè)置過濾器

    • 也就是自定義一個(gè)類實(shí)現(xiàn)InputFilter接口,復(fù)寫filter這個(gè)方法在里面進(jìn)行相關(guān)邏輯
  • 方案三:通過布局文件中,控件的屬性來控制

    • 例如 maxLength、inputType、minLength等

需求

最近在開發(fā)app的時(shí)候,收到了這樣的需求,也就是打賞金額,用戶可以自定義金額,并且需要用戶輸入的金額不能大于500并且限制小數(shù)點(diǎn)后兩位小數(shù),也就是最多輸入499.99元。那么這個(gè)只能自己自定義了。可以看到,這個(gè)需求以上的三種方式,第三種并不能達(dá)到這樣的邏輯要求,暫時(shí)排除,也就是只有方案一和方案二了.
關(guān)于google為啥有這樣的三種方式控制EditText相關(guān)操作,可以查看這個(gè)InputFilter詳解、TextWatcher詳解 所以接下來可以給出最終的一個(gè)實(shí)現(xiàn)方案,那就是實(shí)現(xiàn)InputFilter接口重寫filter這個(gè)方法來實(shí)現(xiàn)上述需求。

給出方案

在方案代碼開始之前,我們需要先了解一下filter方法的各個(gè)參數(shù)的含義:

CharSequence filter (CharSequence source, 
                int start, 
                int end, 
                Spanned dest, 
                int dstart, 
                int dend)

參數(shù)簡(jiǎn)介

  • source 新輸入的字符串
  • start 新輸入的字符串起始下標(biāo),一般為0
  • end 新輸入的字符串終點(diǎn)下標(biāo),一般為source長(zhǎng)度-1
  • dest 輸入之前文本的內(nèi)容
  • dstart 原內(nèi)容起始坐標(biāo) 一般為0
  • dend 原內(nèi)容終點(diǎn)坐標(biāo),一般為dest長(zhǎng)度-1

可以看出我們可以獲取到原本輸入的字符串,還有我們即將輸入的字符串,然后關(guān)于光標(biāo)所在的位置(可以的出來的),而且我們還可以得到原字符串和即將輸入字符串的起始坐標(biāo),那么我們就來搞事情吧。廢話不多說,直接上代碼

/**
 * Created by ruolanmingyue on 2017/10/26.
 *
 * @function 用于過濾輸入      防止輸入大于500元還有就是限制小數(shù)點(diǎn)之后兩位
 */

public class EditInputFilter implements InputFilter {

    /**
     * 最大數(shù)字
     */
    public static final int MAX_VALUE = 500;

    /**
     * 小數(shù)點(diǎn)后的數(shù)字的位數(shù)
     */
    public static final int POINTER_LENGTH = 2;

    private static final String POINTER = ".";

    Pattern p;

    public EditInputFilter() {
        //用于匹配輸入的是0-9  .  這幾個(gè)數(shù)字和字符
        p = Pattern.compile("([0-9]|\\.)*");
    }

    /**
     * source    新輸入的字符串
     * start    新輸入的字符串起始下標(biāo),一般為0
     * end    新輸入的字符串終點(diǎn)下標(biāo),一般為source長(zhǎng)度-1
     * dest    輸入之前文本框內(nèi)容
     * dstart    原內(nèi)容起始坐標(biāo),一般為0
     * dend    原內(nèi)容終點(diǎn)坐標(biāo),一般為dest長(zhǎng)度-1
     */

    @Override
    public CharSequence filter(CharSequence source, int start, int end,
                               Spanned dest, int dstart, int dend) {

        String sourceText = source.toString();
        String destText = dest.toString();
//驗(yàn)證刪除等按鍵
        if (TextUtils.isEmpty(sourceText)) {
            if (dstart == 0 && destText.indexOf(POINTER) == 1) {//保證小數(shù)點(diǎn)不在第一個(gè)位置
                return "0";
            }
            return "";
        }
        Matcher matcher = p.matcher(source);
        //已經(jīng)輸入小數(shù)點(diǎn)的情況下,只能輸入數(shù)字
        if (destText.contains(POINTER)) {
            if (!matcher.matches()) {
                return "";
            } else {
                if (POINTER.equals(source)) { //只能輸入一個(gè)小數(shù)點(diǎn)
                    return "";
                }
            }
            //驗(yàn)證小數(shù)點(diǎn)精度,保證小數(shù)點(diǎn)后只能輸入兩位
            int index = destText.indexOf(POINTER);
            int length = destText.trim().length() - index;
            if (length > POINTER_LENGTH && dstart > index) {
                return "";
            }
        } else {
            //沒有輸入小數(shù)點(diǎn)的情況下,只能輸入小數(shù)點(diǎn)和數(shù)字,但首位不能輸入小數(shù)點(diǎn)和0
            if (!matcher.matches()) {
                return "";
            } else {
                if ((POINTER.equals(source)) && dstart == 0) {//第一個(gè)位置輸入小數(shù)點(diǎn)的情況
                    return "0.";
                } else if ("0".equals(source) && dstart == 0) {
                    return "";
                }
            }
        }
//        dstart
        //修復(fù)當(dāng)光標(biāo)定位到第一位的時(shí)候 還能輸入其他的    這個(gè)是為了修復(fù)以下的情況
        /**
         * <>
         *     當(dāng)如下情況的時(shí)候  也就是 已經(jīng)輸入了23.45   這個(gè)時(shí)候限制是500元
         *     那么這個(gè)時(shí)候如果把光標(biāo)移動(dòng)2前面  也就是第0位  在輸入一個(gè)5  那么這個(gè)實(shí)際的參與下面的
         *     判斷的sumText > MAX_VALUE  是23.455  這個(gè)是不大于 500的   但是實(shí)際情況是523  這個(gè)時(shí)候
         *     已經(jīng)大于500了  所以之前的是存在bug的   這個(gè)要進(jìn)行修正 也就是拿到的比較數(shù)應(yīng)該是523.45  而不是23.455
         *     所以有了下面的分隔  也就是  把23.45  (因?yàn)檫@個(gè)時(shí)候dstart=0)  分隔成 ""  和23.45  然后把  5放到中間
         *     進(jìn)行拼接 也就是  "" + 5 + 23.45  也就是523.45  然后在進(jìn)行和500比較
         *     還有一個(gè)比較明顯的就是   23.45   這個(gè)時(shí)候光標(biāo)在2和3 之間  那么如果修正之前  是23.455   修正之后  dstart = 1
         *     這個(gè)時(shí)候分隔是 "2"  "3.45"   這個(gè)時(shí)候拼接是253.45  然后和500比較  以此類推
         * </>
         */
        String first = destText.substring(0,dstart);

        String second = destText.substring(dstart,destText.length());
//        dend
        String sum = first + sourceText + second;
        //驗(yàn)證輸入金額的大小
        double sumText = Double.parseDouble(sum);
        //這里得到輸入完之后需要計(jì)算的金額  如果這個(gè)金額大于了事先設(shè)定的金額,那么久直接返回  不需要加入輸入的字符
        if (sumText > MAX_VALUE) {
        //
            Toast.makeText(MyApp.getContext(), MyApp.getContext().getResources().getString(R.string.appreciate_input), Toast.LENGTH_SHORT).show();
            return dest.subSequence(dstart, dend);
        }
        //如果輸入的金額小于事先規(guī)定的金額
        return dest.subSequence(dstart, dend) + sourceText;
    }
}

使用方式

 EditText editText = new EditText(getContext());
        
        InputFilter[] filters = {new EditInputFilter()};
        
        editText.setFilters(filters);

參考文檔

  • Android實(shí)現(xiàn)EditText輸入金額
    • 但是這個(gè)文章寫的有bug,發(fā)現(xiàn)的bug如下兩個(gè)
      • 1、輸入金額之后,當(dāng)手動(dòng)改edittext里面的光標(biāo)的時(shí)候,比如剛開始輸入的是23.22元,這個(gè)時(shí)候把光標(biāo)移動(dòng)到2和3之間,那么我們還可以輸入2223.22元,也就是不符合不能大于500元需求,這個(gè)在上面的說明中有詳細(xì)的說明
      • 2、當(dāng)改動(dòng)光標(biāo)在.后面的時(shí)候,也是可以說入數(shù)字的,也就是不符合輸入數(shù)字限制兩位小數(shù)要求
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容