Android EditText 限制输入 金额 保留两位小数 InputFilter理解

本文深入解析在Android开发中如何利用InputFilter实现对金额输入的精确控制,包括限制小数点位置、防止非法输入及保留固定小数位数等实用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

在 EditText中经常要限制输入的内容,比如在输入金额的地方,我们通常需要限制它“只能输入数字和小数点”、“保留两位小数”、“金额最前面不能出现0”、“小数点不能出现在第一位”

分析问题:

限制输入一般有下面几种方法:

  • 在布局文件里给EditText增加属性:android:inputType=“numberDecimal”,对应的代码设置:
//java代码
editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL)

//Kotlin代码
editText.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
  • 在布局文件里设置属性:android:digits=“123456789.”,对应的代码设置:
//Kotlin代码
class MoneyKeyListener : NumberKeyListener() {
        override fun getInputType(): Int {//键盘类型
            return InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
        }

        override fun getAcceptedChars(): CharArray {
            return "123456789.".toCharArray()
        }

    }
  • 使用DigitsKeyListener,DigitsKeyListener是继承自NumberKeyListener.java 代码示例:
//Kotlin代码
keyListener = DigitsKeyListener.getInstance(false, true)//第一个参数表示是否允许输入(+-),第二个参数表示是否允许输入小数点(.)

上面这些方法只能用于简单的限制输入,想要更加灵活的自定义的限制输入的内容,则需要用到今天的主角“InputFilter

解决问题:

InputFilter是一个接口,用来过滤文本框中输入的内容,里面定义了一个filter方法,包含有以下几个参数:

  • source: CharSequence, //将要输入的字符串,如果是删除操作则为空字符串
  • start: Int, //将要输入的字符串起始下标,一般为0
  • end: Int, //start + source字符的长度
  • dest: Spanned, //输入之前文本框中的内容
  • dstart: Int, //将会被替换的起始位置
  • dend: Int //dstart+将会被替换的字符串长度
  • 返回值 :CharSequence //方法返回的值将会替换掉dest字符串中dstartd位置到dend位置之间字符,返回source表示不做任何处理,返回空字符串""表示不输入任何字符
为了便于理解这些参数的意义打印出了一些Log:
  • 连续输入1、2、3、4、5、6,输入框显示:123456,日志如下:
D/MoneyInputFilter: [source:1][start:0][end:1][dest:][dstart:0][dend:0]
D/MoneyInputFilter: [source:2][start:0][end:1][dest:1][dstart:1][dend:1]
D/MoneyInputFilter: [source:3][start:0][end:1][dest:12][dstart:2][dend:2]
D/MoneyInputFilter: [source:4][start:0][end:1][dest:123][dstart:3][dend:3]
D/MoneyInputFilter: [source:5][start:0][end:1][dest:1234][dstart:4][dend:4]
D/MoneyInputFilter: [source:6][start:0][end:1][dest:12345][dstart:5][dend:5]
  • 删除6 ,输入框显示:12345,日志如下:
D/MoneyInputFilter: [source:][start:0][end:0][dest:123456][dstart:5][dend:6]
  • 光标定位到3后面,删除3,输入框显示:1245,日志如下:
D/MoneyInputFilter: [source:][start:0][end:0][dest:12345][dstart:2][dend:3]
  • 选中2和4,输入3,输入框显示:135,日志如下:
D/MoneyInputFilter: [source:3][start:0][end:1][dest:1245][dstart:1][dend:3]
  • 选中3,从其他地方粘贴"234",输入框显示:12345,日志如下:
D/MoneyInputFilter: [source:234][start:0][end:3][dest:135][dstart:1][dend:2]
理解了各个参数意义就可以根据项目需要增加各种输入限制
完整金额过滤器代码(Kotlin):
/**
 * 金额输入过滤器
 * 1、不允许第一个字符为"."
 * 2、不允许出现0123、0456这类字符串
 * 3、保留两位小数
 *
 * @author zhujie
 * @date 2019/6/24
 * @time 15:40
 */
class MoneyInputFilter : InputFilter {
    companion object {
        val POINT_LENGTH = 2//保留小数点位数
    }

    override fun filter(
        source: CharSequence,//将要输入的字符串,如果是删除操作则为空
        start: Int,//将要输入的字符串起始下标,一般为0
        end: Int,//start + source字符的长度
        dest: Spanned,//输入之前文本框中的内容
        dstart: Int,//将会被替换的起始位置
        dend: Int//dstart+将会被替换的字符串长度
    ): CharSequence {//方法返回的值将会替换掉dest字符串中dstartd位置到dend位置之间字符,返回source表示不做任何处理,返回空字符串""表示不输入任何字符
        Log.d("MoneyInputFilter", "[source:$source][start:$start][end:$end][dest:$dest][dstart:$dstart][dend:$dend]")

        val start = dest.subSequence(0, dstart)
        val end = dest.subSequence(dend, dest.length)
        val target = start.toString() + source + end//字符串变化后的结果
        val backup = dest.subSequence(dstart, dend)//将要被替换的字符串

        if (target.indexOf(".") == 0) {//不允许第一个字符为.
            return backup
        }

        if (target.startsWith("0") && !target.startsWith("0.") && "0" != target) {//不允许出现0123、0456这类字符串
            return backup
        }

        //限制小数点后面只能有两位小数
        val index = target.indexOf(".")
        if (index >= 0 && index + POINT_LENGTH + 2 <= target.length) {
            return backup
        }

        return source
    }
}
使用方法:
//java
editText.setFilters(new InputFilter[]{new MoneyInputFilter ()});
//Kotlin
editText.filters = arrayOf(MoneyInputFilter())
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值