给EditText添加一个工具方法,使其支持仅保留到第N位小数

需求:项目中需要一个能截取到小数点后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方法;
        *   方法定义:
        *   void	addTextChangedListener(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());
            }
        };
    }
}



MoneyUtil:


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);
		}
	}
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值