EditText金額輸入(限制輸入金額大小和小數點后兩位)

EditText金額輸入(限制輸入金額大小和小數點后兩位)

標簽(空格分隔): Android開發


Android中控制EditText輸入內容、長度的方法有三種

  • 方案一:

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

    • 也就是自定義一個類實現InputFilter接口,復寫filter這個方法在里面進行相關邏輯
  • 方案三:通過布局文件中,控件的屬性來控制

    • 例如 maxLength、inputType、minLength等

需求

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

給出方案

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

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

參數簡介

  • source 新輸入的字符串
  • start 新輸入的字符串起始下標,一般為0
  • end 新輸入的字符串終點下標,一般為source長度-1
  • dest 輸入之前文本的內容
  • dstart 原內容起始坐標 一般為0
  • dend 原內容終點坐標,一般為dest長度-1

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

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

public class EditInputFilter implements InputFilter {

    /**
     * 最大數字
     */
    public static final int MAX_VALUE = 500;

    /**
     * 小數點后的數字的位數
     */
    public static final int POINTER_LENGTH = 2;

    private static final String POINTER = ".";

    Pattern p;

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

    /**
     * source    新輸入的字符串
     * start    新輸入的字符串起始下標,一般為0
     * end    新輸入的字符串終點下標,一般為source長度-1
     * dest    輸入之前文本框內容
     * dstart    原內容起始坐標,一般為0
     * dend    原內容終點坐標,一般為dest長度-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();
//驗證刪除等按鍵
        if (TextUtils.isEmpty(sourceText)) {
            if (dstart == 0 && destText.indexOf(POINTER) == 1) {//保證小數點不在第一個位置
                return "0";
            }
            return "";
        }
        Matcher matcher = p.matcher(source);
        //已經輸入小數點的情況下,只能輸入數字
        if (destText.contains(POINTER)) {
            if (!matcher.matches()) {
                return "";
            } else {
                if (POINTER.equals(source)) { //只能輸入一個小數點
                    return "";
                }
            }
            //驗證小數點精度,保證小數點后只能輸入兩位
            int index = destText.indexOf(POINTER);
            int length = destText.trim().length() - index;
            if (length > POINTER_LENGTH && dstart > index) {
                return "";
            }
        } else {
            //沒有輸入小數點的情況下,只能輸入小數點和數字,但首位不能輸入小數點和0
            if (!matcher.matches()) {
                return "";
            } else {
                if ((POINTER.equals(source)) && dstart == 0) {//第一個位置輸入小數點的情況
                    return "0.";
                } else if ("0".equals(source) && dstart == 0) {
                    return "";
                }
            }
        }
//        dstart
        //修復當光標定位到第一位的時候 還能輸入其他的    這個是為了修復以下的情況
        /**
         * <>
         *     當如下情況的時候  也就是 已經輸入了23.45   這個時候限制是500元
         *     那么這個時候如果把光標移動2前面  也就是第0位  在輸入一個5  那么這個實際的參與下面的
         *     判斷的sumText > MAX_VALUE  是23.455  這個是不大于 500的   但是實際情況是523  這個時候
         *     已經大于500了  所以之前的是存在bug的   這個要進行修正 也就是拿到的比較數應該是523.45  而不是23.455
         *     所以有了下面的分隔  也就是  把23.45  (因為這個時候dstart=0)  分隔成 ""  和23.45  然后把  5放到中間
         *     進行拼接 也就是  "" + 5 + 23.45  也就是523.45  然后在進行和500比較
         *     還有一個比較明顯的就是   23.45   這個時候光標在2和3 之間  那么如果修正之前  是23.455   修正之后  dstart = 1
         *     這個時候分隔是 "2"  "3.45"   這個時候拼接是253.45  然后和500比較  以此類推
         * </>
         */
        String first = destText.substring(0,dstart);

        String second = destText.substring(dstart,destText.length());
//        dend
        String sum = first + sourceText + second;
        //驗證輸入金額的大小
        double sumText = Double.parseDouble(sum);
        //這里得到輸入完之后需要計算的金額  如果這個金額大于了事先設定的金額,那么久直接返回  不需要加入輸入的字符
        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);
        }
        //如果輸入的金額小于事先規定的金額
        return dest.subSequence(dstart, dend) + sourceText;
    }
}

使用方式

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

參考文檔

  • Android實現EditText輸入金額
    • 但是這個文章寫的有bug,發現的bug如下兩個
      • 1、輸入金額之后,當手動改edittext里面的光標的時候,比如剛開始輸入的是23.22元,這個時候把光標移動到2和3之間,那么我們還可以輸入2223.22元,也就是不符合不能大于500元需求,這個在上面的說明中有詳細的說明
      • 2、當改動光標在.后面的時候,也是可以說入數字的,也就是不符合輸入數字限制兩位小數要求
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容