给EditText添加一个工具方法,使其支持仅保留到第N位小数
来源:互联网 发布:专业视频制作软件 编辑:程序博客网 时间:2024/04/30 20:14
需求:项目中需要一个能截取到小数点后2位的edittext,且在输入的时候实时的监听输入变化,将金额内容转换成中文金额大写的内容;
参考:http://www.blogjava.net/fastunit/archive/2008/03/25/188537.html 大写金额
其中几点可能需要注意:
1. 不希望用自定义控件,那样耦合性会很大,个人觉得没必要;
2. 利用现有edittext控件的各种特性和方法为我们实现想要的效果服务:
a. android:inputType="numberDecimal" 在布局相应控件直接定义该属性,帮助我们限制该输入框只能输入数字(含小数)
b. android:maxLength="12" 设置可以接受的金额长度(包含小数点)
c. 监听edittext控件的addTextChangedListener方法,在afterTextChanged接口中处理即将显示到输入框中的值;而在这里添加一个回掉,方便主线程中处理相应的逻辑,比如上面需求中需要的,并行显示输入金额的中文大写(感谢参考链接中,哪位仁兄提供的一系列方法)。
效果:
项目代码:
布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:text="测试EditText,支持仅能输入小数点后两位" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/textView" /> <!-- android:maxLength="12" 连上小数点最多可以输入的字符--> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:inputType="numberDecimal" android:ems="12" android:maxLength="12" android:id="@+id/editText" android:layout_below="@+id/textView"/> <TextView android:text="等待输入" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_below="@id/editText" android:id="@+id/showTextView" /></RelativeLayout>
主Activity:
package top.playinteractive.testapp;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.widget.EditText;import android.widget.TextView;import top.playinteractive.testapp.log.CommonLog;import top.playinteractive.testapp.log.LogFactory;import top.playinteractive.testapp.utils.MoneyUtil;import top.playinteractive.testapp.utils.UIUtils;public class MainActivity extends ActionBarActivity { private static final CommonLog log; static { log = LogFactory.createLog(); } private TextView showTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); showTextView = (TextView) findViewById(R.id.showTextView); ((EditText) findViewById(R.id.editText)).addTextChangedListener(UIUtils.getDecimalRestrictionsTextWatcher(3, new UIUtils.DecimalRestrictionsCallBack() { @Override public void afterTextChanged(String txt) { log.e(MoneyUtil.toChinese(txt)); showTextView.setText(MoneyUtil.toChinese(txt)); } })); /* * 以下为测试代码: * 1、复写EditText继承自 android.widget.TextView 的addTextChangedListener方法; * 方法定义: * voidaddTextChangedListener(TextWatcher watcher) Adds a TextWatcher to the list of those whose methods are called whenever this TextView's text changes. 2、该方法在textview的setText被调用时之后会被通知,在这里会被分为3个阶段调用该接口(TextWatcher)中的3个实现,在每个实现中都可以对文本进行处理; * */// ((EditText) findViewById(R.id.editText)).addTextChangedListener(new TextWatcher() {//// /*// * This method is called to notify you that, within s, the count characters beginning at start are about// * to be replaced by new text with length after. It is an error to attempt to make changes to s from this callback// * */// @Override// public void beforeTextChanged(CharSequence s, int start, int count, int after) {//// log.e("---beforeTextChanged---");//// log.e(s);//上一次显示的文本//// log.e(start);//准备插入的字符将以这个位置进行插入(0为起始位置)//// log.e(count);//0输入的时候、1删除的时候//// log.e(after);//输入的个数,始终为1//// log.e("---...---");// }//// @Override// public void onTextChanged(CharSequence s, int start, int before, int count) {//// log.e("---onTextChanged---");//// log.e(s);//当前输入的文本//// log.e(start);//准备插入的字符将以这个位置进行插入(0为起始位置)//// log.e(count);//1输入的时候、0删除的时候//// log.e("---...---");// }//// @Override// public void afterTextChanged(Editable s) {//// log.e("---afterTextChanged---");//// log.e(s);//最后将会显示到输入框的值//// log.e("---...---");// if (null != s) {// String temp = s.toString();// int posDot = temp.indexOf(".");// if (posDot <= 0) return;// //如果字符串的长度(加上小数点) - 小数点所在位置,再减去 1,得到小数点后的字符数量,如果大于2就标识用户试图输入2位以上的小数// if (temp.length() - posDot - 1 > 2) {// //用小数点后两位 替换 小数点后面的字符(后4位)// s.delete(posDot + 3, posDot + 4);// }// }// }// }); }}
工具类:
UIUtils:
package top.playinteractive.testapp.utils;import android.text.Editable;import android.text.TextWatcher;/** * Created by zhaojin on 15/3/3. */public class UIUtils { /** * 保留几位小数 * @param digits 保留的小数位数 * */ public static TextWatcher getDecimalRestrictionsTextWatcher(final int digits) { return 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) { if (null != s || s.length() != 0) { String temp = s.toString(); int posDot = temp.indexOf("."); if (posDot <= 0) return; //如果字符串的长度(加上小数点) - 小数点所在位置,再减去 1,得到小数点后的字符数量,如果大于2就标识用户试图输入2位以上的小数 if (temp.length() - posDot - 1 > digits) { //用小数点后两位 替换 小数点后面的字符(后4位) s.delete(posDot + digits + 1, posDot + digits + 2); } } } }; } public interface DecimalRestrictionsCallBack{ void afterTextChanged(String txt); } /** * 保留几位小数 * @param digits 保留的小数位数 * */ public static TextWatcher getDecimalRestrictionsTextWatcher(final int digits, final DecimalRestrictionsCallBack callback) { return 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) { if (null != s || s.length() != 0) { if(s.length() == 1 && s.toString().equals(".")){ s.replace(0,s.length(),"0."); } String temp = s.toString(); int posDot = temp.indexOf("."); if (posDot > 0) { //如果字符串的长度(加上小数点) - 小数点所在位置,再减去 1,得到小数点后的字符数量,如果大于2就标识用户试图输入2位以上的小数 if (temp.length() - posDot - 1 > digits) { //用小数点后两位 替换 小数点后面的字符(后4位) s.delete(posDot + digits + 1, posDot + digits + 2); } } } callback.afterTextChanged(s.toString()); } }; }}
package top.playinteractive.testapp.utils;/** * Created by zhaojin on 15/3/4. */public class MoneyUtil { /** * 大写数字 */ private static final String[] NUMBERS = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"}; /** * 整数部分的单位 */ private static final String[] IUNIT = {"元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万", "拾", "佰", "仟"}; /** * 小数部分的单位 */ private static final String[] DUNIT = {"角", "分", "厘"}; /** * 得到大写金额。 */ public static String toChinese(String str) { str = str.replaceAll(",", "");// 去掉"," String integerStr;// 整数部分数字 String decimalStr;// 小数部分数字 // 初始化:分离整数部分和小数部分 if (str.indexOf(".") > 0) { integerStr = str.substring(0, str.indexOf(".")); decimalStr = str.substring(str.indexOf(".") + 1); } else if (str.indexOf(".") == 0) { integerStr = ""; decimalStr = str.substring(1); } else { integerStr = str; decimalStr = ""; } // integerStr去掉首0,不必去掉decimalStr的尾0(超出部分舍去) if (!integerStr.equals("")) { integerStr = Long.toString(Long.parseLong(integerStr)); if (integerStr.equals("0")) { integerStr = ""; } } // overflow超出处理能力,直接返回 if (integerStr.length() > IUNIT.length) { throw new RuntimeException("输入数字长度大于IUNIT.length"+IUNIT.length); } int[] integers = toArray(integerStr);// 整数部分数字 boolean isMust5 = isMust5(integerStr);// 设置万单位 int[] decimals = toArray(decimalStr);// 小数部分数字 return getChineseInteger(integers, isMust5) + getChineseDecimal(decimals); } /** * 整数部分和小数部分转换为数组,从高位至低位 */ private static int[] toArray(String number) { int[] array = new int[number.length()]; for (int i = 0; i < number.length(); i++) { array[i] = Integer.parseInt(number.substring(i, i + 1)); } return array; } /** * 得到中文金额的整数部分。 */ private static String getChineseInteger(int[] integers, boolean isMust5) { StringBuffer chineseInteger = new StringBuffer(""); int length = integers.length; for (int i = 0; i < length; i++) { // 0出现在关键位置:1234(万)5678(亿)9012(万)3456(元) // 特殊情况:10(拾元、壹拾元、壹拾万元、拾万元) String key = ""; if (integers[i] == 0) { if ((length - i) == 13)// 万(亿)(必填) key = IUNIT[4]; else if ((length - i) == 9)// 亿(必填) key = IUNIT[8]; else if ((length - i) == 5 && isMust5)// 万(不必填) key = IUNIT[4]; else if ((length - i) == 1)// 元(必填) key = IUNIT[0]; // 0遇非0时补零,不包含最后一位 if ((length - i) > 1 && integers[i + 1] != 0) key += NUMBERS[0]; } chineseInteger.append(integers[i] == 0 ? key : (NUMBERS[integers[i]] + IUNIT[length - i - 1])); } return chineseInteger.toString(); } /** * 得到中文金额的小数部分。 */ private static String getChineseDecimal(int[] decimals) { StringBuffer chineseDecimal = new StringBuffer(""); for (int i = 0; i < decimals.length; i++) { // 舍去3位小数之后的 if (i == 3) break; chineseDecimal.append(decimals[i] == 0 ? "" : (NUMBERS[decimals[i]] + DUNIT[i])); } return chineseDecimal.toString(); } /** * 判断第5位数字的单位"万"是否应加。 */ private static boolean isMust5(String integerStr) { int length = integerStr.length(); if (length > 4) { String subInteger = ""; if (length > 8) { // 取得从低位数,第5到第8位的字串 subInteger = integerStr.substring(length - 8, length - 4); } else { subInteger = integerStr.substring(0, length - 4); } return Integer.parseInt(subInteger) > 0; } else { return false; } } public static void main(String[] args) { String number = "1.23"; System.out.println(number + " " + MoneyUtil.toChinese(number)); number = "1234567890123456.123"; System.out.println(number + " " + MoneyUtil.toChinese(number)); number = "0.0798"; System.out.println(number + " " + MoneyUtil.toChinese(number)); number = "10,001,000.09"; System.out.println(number + " " + MoneyUtil.toChinese(number)); number = "01.107700"; System.out.println(number + " " + MoneyUtil.toChinese(number)); }}
LogFactory:
package top.playinteractive.testapp.log;public class LogFactory {private static final String TAG = "playinteractive";private static CommonLog log = null;public static CommonLog createLog() {if (log == null) {log = new CommonLog();}log.setTag(TAG);return log;}public static CommonLog createLog(String tag) {if (log == null) {log = new CommonLog();}if (tag == null || tag.length() < 1) {log.setTag(TAG);} else {log.setTag(tag);}return log;}}
CommonLog:
package top.playinteractive.testapp.log;import android.util.Log;public class CommonLog {private String tag = "CommonLog";public static int logLevel = Log.VERBOSE;public static boolean isDebug = true;public CommonLog() {}public CommonLog(String tag) {this.tag = tag;}public void setTag(String tag) {this.tag = tag;}private String getFunctionName() {StackTraceElement[] sts = Thread.currentThread().getStackTrace();if (sts == null) {return null;}for (StackTraceElement st : sts) {if (st.isNativeMethod()) {continue;}if (st.getClassName().equals(Thread.class.getName())) {continue;}if (st.getClassName().equals(this.getClass().getName())) {continue;}return "[" + Thread.currentThread().getId() + ": "+ st.getFileName() + ":" + st.getLineNumber() + "]";}return null;}public void info(Object str) {if (logLevel <= Log.INFO) {String name = getFunctionName();String ls = (name == null ? str.toString() : (name + " - " + str));Log.i(tag, ls);}}public void i(Object str) {if (isDebug) {info(str);}}public void verbose(Object str) {if (logLevel <= Log.VERBOSE) {String name = getFunctionName();String ls = (name == null ? str.toString() : (name + " - " + str));Log.v(tag, ls);}}public void v(Object str) {if (isDebug) {verbose(str);}}public void warn(Object str) {if (logLevel <= Log.WARN) {String name = getFunctionName();String ls = (name == null ? str.toString() : (name + " - " + str));Log.w(tag, ls);}}public void w(Object str) {if (isDebug) {warn(str);}}public void error(Object str) {if (logLevel <= Log.ERROR) {String name = getFunctionName();String ls = (name == null ? str.toString() : (name + " - " + str));Log.e(tag, ls);}}public void error(Exception ex) {if (logLevel <= Log.ERROR) {StringBuffer sb = new StringBuffer();String name = getFunctionName();StackTraceElement[] sts = ex.getStackTrace();if (name != null) {sb.append(name + " - " + ex + "\r\n");} else {sb.append(ex + "\r\n");}if (sts != null && sts.length > 0) {for (StackTraceElement st : sts) {if (st != null) {sb.append("[ " + st.getFileName() + ":"+ st.getLineNumber() + " ]\r\n");}}}Log.e(tag, sb.toString());}}public void e(Object str) {if (isDebug) {error(str);}}public void e(Exception ex) {if (isDebug) {error(ex);}}public void debug(Object str) {if (logLevel <= Log.DEBUG) {String name = getFunctionName();String ls = (name == null ? str.toString() : (name + " - " + str));Log.d(tag, ls);}}public void d(Object str) {if (isDebug) {debug(str);}}}
0 0
- 给EditText添加一个工具方法,使其支持仅保留到第N位小数
- Java使四舍五入和保留N位小数的方法
- C#保留N位小数的方法
- lua保留n位小数方法
- JavaScript保留N位小数的方法
- C#中保留小数N位小数方法整理
- C#中保留小数N位小数方法整理
- EditText 保留两位小数
- EditText 保留两位小数
- EditText 保留两位小数
- 保留小数后N位
- 四舍五入,保留N位小数
- C#小数保留N位
- java:保留n位小数
- double保留n位小数
- float-保留N位小数
- java保留n位小数
- js 保留n位小数
- 小毛驴(xml)试乘记(三):jQuery方法
- springmvc @RequestMapping不要写死
- Java复习--线程基本概念
- 零碎的
- 2015年 国家超级计算济南中心 工作日志
- 给EditText添加一个工具方法,使其支持仅保留到第N位小数
- 利用 onload 事件监控跨站资源
- OGG-02050 Not enough database memory to honor requested MAX_SGA_SIZE
- block 使用小节(防止循环引用)
- iOS开发的22个奇谲巧技
- Android开发Eclipse连接真机
- andoid自学交流
- P2P通信
- mysql数据库优化2