Android金额输入控件

来源:互联网 发布:数据库权限管理制度 编辑:程序博客网 时间:2024/06/05 15:49

金额输入控件

最近在做一个金融的项目,里面有关于金额的判断和限制金额的输入,然后就发现了些问题。比如我们输入金额的时候肯定只能输入数字和点号,不能输入其他的字符;还有进行金额判断的时候很麻烦,比如要金额不能为0878787.98、.898或者0000000.98等等这样的。每次都要进行这样的判断很麻烦,又很耗时而且又容易出错,然后就在想能不能自己自定义一个控件来限制输入规范它,并且能将判断在内部处理。

首先我们要控制输入类型,这个很简单,我们只需要设置EditText的inputType类型为numberDecimal就行了。然后我们需要控制输入内容了,比如我们第一位输入的是为0,那么下一位必须为点号,不能继续输入数字,那么我们怎么实现这样的功能呢?

然后我们去看EditText的源码,发现没有。

这里写图片描述

然后我们发现EditText继承TextView,那么我们去看下TextView的源码

这里写图片描述

我们在这个发现了setFilters这个方法,感觉是,我们继续看下去

这里写图片描述

纯英文的,看不懂,没关系,我们百度看这个是不是我们需要找的

TextView和EditText中的setFilters方法说明

看来这个确实是我们要找的(在这篇文章中写的很清楚了,这里就不再说了),那么我们怎样设置规则呢?

好了,现在我们要开始设置规则了,那我们先考虑下,我们需要设置哪些规则?

  • 如果以0开头
    • 则下一位必须是点
    • 0和点之间不能输入任何数字
  • 如果不是0开头
    • 不能将0放在字符串的第一位
    • 第一位不能输入“.”
  • 如果第一位为“.”,则点号后面不能继续输入
  • 保留两位小数
  • 验证删除等按键

将规则写清楚之后,我们就直接上代码吧

public class AmountFilter implements InputFilter {private final String TAG = "AmountFilter";Pattern mPattern;//正则匹配private static final int POINTER_AFTER_LENGTH = 2; //小数点后的位数private static final String POINTER = ".";private static final String ZERO = "0";public AmountFilter() {    //正则表达式    mPattern = Pattern.compile("([0-9]|\\.)*");}/** * @param source    新输入的字符串 * @param start     新输入的字符串起始下标,一般为0 * @param end       新输入的字符串终点下标,一般为source长度-1 * @param dest      输入之前文本框内容 * @param dstart    原内容起始坐标,一般为0 * @param dend      原内容终点坐标,一般为dest长度-1 * @return          输入内容 */@Overridepublic 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)) {        return  "";    }    //如果是0开头,则下一位必须是点    if (destText.startsWith(ZERO)){        if (!TextUtils.equals(POINTER,source) && destText.length() == 1){            sourceText = "";        }        //0和点之间不能输入任何数字        else if (destText.contains(POINTER)){            int point = destText.indexOf(POINTER);            if (dstart <= point && dstart > 0){                sourceText = "";            }        }        else if (!destText.contains(POINTER)                && dstart != 0 && destText.length() != 1){            sourceText = "";        }    }    //不能将0放在字符串的第一位    if (!TextUtils.isEmpty(destText) && dstart == 0            && TextUtils.equals(ZERO,sourceText)            && !destText.startsWith(POINTER)){        sourceText = "";    }    //第一位不能输入“.”    if (TextUtils.isEmpty(destText) && TextUtils.equals(sourceText,POINTER)){        sourceText = "";    }    //如果第一位为“.”,则点号后面不能继续输入    if (destText.startsWith(POINTER) && dstart != 0){        sourceText = "";    }    //保留POINTER_AFTER_LENGTH位小数   if (!destText.contains(POINTER) && TextUtils.equals(POINTER,sourceText)){      int decimal = destText.length() - dstart;       if (decimal > 2){           sourceText = "";       }   }else if (destText.contains(POINTER)){      int point = destText.indexOf(POINTER);       if (dstart > point && (destText.length() - point) >= 3){           sourceText = "";       }   }    String result = dest.subSequence(dstart, dend) + sourceText;    return result;}

}

那么我们自定义一个AmountEditText

SuppressLint("AppCompatCustomView")public class AmountEditText extends EditText {private Context mContext;public AmountEditText(Context context) {    super(context);    init(context);}public AmountEditText(Context context, AttributeSet attrs) {    super(context, attrs);    init(context);}public AmountEditText(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);    init(context);}private void init(Context context){    mContext = context;}@Overridepublic void setFilters(InputFilter[] filters) {   filters = new InputFilter[]{new AmountFilter()};    super.setFilters(filters);}}

那么我们运行下看效果吧

这里写图片描述

可以看到只能输入两位小数,然后小数位就不能输入了。如果第一位输入为0,呢后以为只能输入点,输入其他的数字无法输入。那么到这里是不是已经完成了呢?不知道大家发现问题没有,有没有可能出现02342这种情况呢,理论上是不会出现的,我们现在试下

这里写图片描述

从图中可以看到是可能出现这种情况的,那么为什么能出现这种情况呢?这是因为InputFilter这能限制输入情况,已经存在的内容是没有办法控制的,那么我们就没有办法了吗?

当然这种情况也是有办法的。上面是对输入内容的限制,那么我们只要对输入结果做一个判断,检验输入结果是否符合规范就行了。

  /** * 输入内容是否符合规则 * @return */public boolean isConformRules(){    String result = super.getText().toString();    if (TextUtils.isEmpty(result)){        return false;    }else if (result.contains(".")){        if (result.startsWith(".")){            return false;        }else if (result.startsWith("0")){            int indexZero = result.indexOf("0");            int indexPoint = result.indexOf(".");            if (indexPoint - indexZero != 1){                return false;            }else if (TextUtils.equals("0.",result)){                return false;            }        }    }else if (!result.contains(".")){        if (result.startsWith("0")){            return false;        }    }    return true;}

当我们输入完成之后,只需调用这个方法进行判断就行了。如果符合规则就返回true,不符合规则为false.那我们来检验一下

这里写图片描述

从图片中可以看到,已经完全ok的。最后,有时我们需要将金额转为分,即将结果*100,这里我们也设置了

 /** * 获取设置倍数 * @return */public int getMultiple() {    return Multiple;}/** * 设置金额倍数 * @param multiple */public void setMultiple(int multiple) {    Multiple = multiple;}

只需在这里设置倍数即可,当然默认倍数为1,即原值不变

最后将Demo上传,需要的同学可以下载,有问题的话也可以在下方留言,谢谢!