Android金额输入控件

金额输入控件

最近在做一个金融的项目,里面有关于金额的判断和限制金额的输入,然后就发现了些问题。比如我们输入金额的时候肯定只能输入数字和点号,不能输入其他的字符;还有进行金额判断的时候很麻烦,比如要金额不能为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          输入内容
 */
@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)) {
        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;
}

@Override
public 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上传,需要的同学可以下载,有问题的话也可以在下方留言,谢谢!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
实现自定义输入金额可以使用 EditText 控件,并对其进行限制和格式化。以下是一个简单的实现方法: 1. 在 XML 文件中添加 EditText 控件,并设置输入类型为数字和小数点: ```xml <EditText android:id="@+id/editTextAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" android:digits="0123456789." /> ``` 2. 在 Java 代码中获取 EditText 控件,并添加 TextWatcher 监听器来限制输入内容和格式化金额: ```java EditText editTextAmount = findViewById(R.id.editTextAmount); editTextAmount.addTextChangedListener(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) { } @Override public void afterTextChanged(Editable s) { String amount = s.toString(); // 限制小数点后只能有两位 if (amount.contains(".")) { if (amount.length() - amount.indexOf(".") > 3) { s.replace(s.length() - 1, s.length(), ""); } } // 限制金额最大值为 9999.99 if (Double.parseDouble(amount) > 9999.99) { s.replace(s.length() - 1, s.length(), ""); } // 格式化金额,每三位加一个逗号 if (amount.length() > 0) { DecimalFormat decimalFormat = new DecimalFormat("#,##0.00"); String formattedAmount = decimalFormat.format(Double.parseDouble(amount)); if (!amount.equals(formattedAmount)) { s.replace(0, s.length(), formattedAmount); } } } }); ``` 这样就可以实现自定义输入金额并格式化显示。注意要处理一些异常情况,例如输入非法字符和超出最大值等。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值