1、概述
本渣渣在支付项目上遇到一个金额输入框。
开始觉得没啥,不就一小小输入框么有啥难的小case~小爷我分分钟弄出来……直到写的时候才发现这个金额输入框还是烦人的,硬是折腾了一下午,分分钟把自己搞秃头的节奏。
想想还是做个笔记吧~ 要不然等脑袋瓜子生锈了 ,下次在遇到想不出了, 就醉了~~~
功能描述##
金额输入框:功能便是很多POS设备上那样开始显示为: 0.00, 当输入数字时便会依次从右添加到输入框。例如依次输入123:输入1 == 0.01,继续输入2 == 0.12 ,随后输入3应该进位变为 3 == 1.23 。
也就是,实现从右向左输入并且保证有且只有俩位小数,至少有一位个位数。
这样的话,普通的输入框变没有办法实现了。
在这里就会遇到的问题大致便是是:
1、数字从右向左显示
2、保证小数位只有俩位,并至少有一位个位。
3、回退键处理(也就是回退时,从右开始删除,数字退位。例如:1.23 -->删除 == 0.12 , 0.12 -->删除 == 0.01 ,0.01 --> 删除 == 0.00 ,0.00 删除不变。)
4、长度无上限
2、思路##
开始的想法是,不就输入金额么,有啥难的,监听下输入的值然后把 用户输入的值 根据不同情况处理下咯额,怎么处理呢,嗯哼,把用户输完的数字拦截到,然后转化下类型。这样的话,用户输入1,把1/100,就是0.01了
用户输入12,12/100 就是 0.12,输入123就是1.23!哎呦妈呀,真™简单!好的除100。
然后就是…哎哎哎怎么小数位只有一位了…我的天,忘了数字有大小限制了。然后数字大了之后出来ABCDE……十六进制我的天……
哎哎,忘了还有删除键……删除乘个十?我也是天真。
一大堆的问题终结了我这个思路。忍不住吐槽自己一句MDZZ。。。
随后又想了几种其他的思路,什么把它变成字符串处理成数字的样子在进行转换,什么得到之前输入的值然后在后面补位……终归是无非达到想要的效果,最多就是很像但是bug一堆!
最后!小哥一个回光返照,额不,灵光一现~决定不在纠结于在“金额”二字上面,也就是我想直接拜托数字这个概念,然后分析了下。感觉如果可以通过一个算法将字符串进行处理 就不会有什么 16进制 ,转化出错,长度上限什么鬼问题了。
可是怎么通过字符串实现呢,分析了半天后,将重心放在了小数点上面“ . ”~
对头!就是这货,视觉上的数字输入和退位,可以看做是小数点的右移和左移。
① 举个输入例子就是:如果开始的字符串默认显示为0.00,此时,用户输入1,输入框中的字符串将会是0.001,我们将小数点向右移动就是00.01,然后在去掉头一个0,就变成了我们想要的0.01。同理,在0.01的基础上输入2,就会是0.012,小数点右移在去除头一个0,就是0.12。
②在举个删除的例子:如果此时的数字时显示为1.23,用户点击删除键,我们将小数点左移一位就是 .123,然后在前面添加个0,就变成了 0.123,去除第三位小数就变成了我们想要的结果 0.12。
这样的话避免了很多了问题,接下来就是实现了~
代码##
1、都说了是EditText,所以这个肯定必不可少哈~一个控制只能输入金额数字的输入框。
...
<EditText
android:id="@+id/edit_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:numeric="decimal" />
...
2、第二步在Activity里面找到editText然后监听他的文本输入。
editText = (EditText) findViewById(R.id.edit_main);
editText.addTextChangedListener(new TextWatcher() {
private String numberStr; //定义一个字符串来得到处理后的金额
@Override
public void beforeTextChanged(CharSequence s, int start, int
count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
int lenght = s.length();
Log.e("Sun", s + "====" + start + "=======" + before + "======" + count);
double number = 0.00; //初始金额
//第一次输入初始化 金额值
if (lenght <= 1){
number = Double.parseDouble(s.toString());
number =number /100;//第一次 长度等于
numberStr = number + "";
}else {
//之后的输入带入算法后将值设置给 金额值
if (s.toString().contains(".")){
numberStr = getMoneyString(s.toString()); //这个方法看第三步
}
}
}
@Override
public void afterTextChanged(Editable s) {
String aa = editText.getText().toString();
Toast.makeText(MainActivity.this, aa + "*****" + numberStr, Toast.LENGTH_SHORT).show();
//在此判断输入框的值是否等于金额的值,如果不相同则赋值,如果不判断监听器将会出现死循环
if (!TextUtils.isEmpty(editText.getText().toString()) && !editText.getText().toString().equals(numberStr)){
Toast.makeText(MainActivity.this,numberStr+"*****",Toast.LENGTH_SHORT).show();
editText.setText(numberStr); //赋值到editText上
editText.setSelection(numberStr.length()); //将光标定位到结尾
}
}
});
3、第三步写一个 处理金额的方法,就是重点方法☆☆☆☆☆
…
//定义一个处理字符串的方法
private String getMoneyString(String money){
String overMoney = "";//结果
String[] pointBoth = money.split("\\.");//分隔点前点后
String beginOne = pointBoth[0].substring(pointBoth[0].length()-1);//前一位
String endOne = pointBoth[1].substring(0, 1);//后一位
//小数点前一位前面的字符串,小数点后一位后面
String beginPoint = pointBoth[0].substring(0,pointBoth[0].length()-1);
String endPoint = pointBoth[1].substring(1);
Log.e("Sun", pointBoth[0]+"==="+pointBoth[1] + "====" + beginOne + "=======" + endOne+"===>"+beginPoint+"=="+endPoint );
//根据输入输出拼点
if (pointBoth[1].length()>2){//说明输入,小数点要往右移
overMoney= pointBoth[0]+endOne+"."+endPoint;//拼接实现右移动
}else if (
pointBoth[1].length()<2){//说明回退,小数点左移
overMoney = beginPoint+"."+beginOne+pointBoth[1];//拼接实现左移
}else {
overMoney = money;
}
//去除点前面的0 或者补 0
String overLeft = overMoney.substring(0,overMoney.indexOf("."));//得到前面的字符串
Log.e("Sun","左邊:"+overLeft+"===去零前"+overMoney);
if (overLeft ==null || overLeft == ""||overLeft.length()<1){//如果没有就补零
overMoney = "0"+overMoney;
}else if(overLeft.length() > 1 && "0".equals(overLeft.subSequence(0, 1))){//如果前面有俩个零
overMoney = overMoney.substring(1);//去第一个0
}
Log.e("Sun","結果:"+overMoney);
return overMoney;
}
…
结尾#
写到这里就 我笔记就写完啦~希望能帮到 有需求写 这个控件但是折腾了半天的小伙伴们~