使用TextWatcher实现EditView的度分秒控制输入。
2016-04-21 10:05
706 查看
项目中有个需求要求在EditView内只能进行度分秒的控制输入,看到参考其他软件的实现效果,自己实现了一下。
输入的时候会自动限定在经纬度数值范围之内,当光标在引号位置时输入无效并自动跳过。
这个效果需要使用TextWatcher。
TextWatcher接口有三个方法,在输入框内容修改的时候会依次执行
s是修改之前输入框的内容
start是新内容插入的位置
count是对影响原有内容的长度,插入操作的时候通常为0
after是插入新内容的长度
start是改变内容的开始位置
before是改变前的内容数量
count是改变内容的长度
s是改变后的内容
根据这三个方法我们可以在内容插入的时候对内容进行修改,然后再次调用setText来实现输入框的限制输入,但是需要注意在调用setText后会重新执行这三个方法,可能导致死循环,因此在满足条件的时候就不要再调用setText了。
我们的要求是限制输入为度分秒,不多说,直接上代码
我实现了三种类型的现在,分别对应纬度、经度和角度,在构造方法里通过参数判断,使用也很简单
后来发现有个InputFilter接口似乎也能实现这个效果,时间有限,以后有空再研究。
输入的时候会自动限定在经纬度数值范围之内,当光标在引号位置时输入无效并自动跳过。
这个效果需要使用TextWatcher。
TextWatcher接口有三个方法,在输入框内容修改的时候会依次执行
beforeTextChanged(CharSequences, int start, int count, int after);
s是修改之前输入框的内容
start是新内容插入的位置
count是对影响原有内容的长度,插入操作的时候通常为0
after是插入新内容的长度
onTextChanged(CharSequences, int start, int before, int count);
start是改变内容的开始位置
before是改变前的内容数量
count是改变内容的长度
afterTextChanged(Editables);
s是改变后的内容
根据这三个方法我们可以在内容插入的时候对内容进行修改,然后再次调用setText来实现输入框的限制输入,但是需要注意在调用setText后会重新执行这三个方法,可能导致死循环,因此在满足条件的时候就不要再调用setText了。
我们的要求是限制输入为度分秒,不多说,直接上代码
import java.util.regex.Matcher; import java.util.regex.Pattern; import android.text.Editable; import android.text.TextWatcher; import android.widget.EditText; /** * 度分秒输入控制器,可以将输入控制在经度、纬度、角度范围之内。 * @author Wkkyo * @date 2016-4-19 * @version 1.0.0 * @code * <code> * EditView editView = findViewById(R.id.editView); * editView.addTextChangedListener(new DMSTextWatcher(editView,0)); * </code> * */ public final class DMSTextWatcher implements TextWatcher{ private String oldText; private boolean backspace = true; private int watchType = 0; private final String MAX_VALUE_N = "90:00:00.00000"; private final String MAX_VALUE_E = "180:00:00.00000"; private final String MAX_VALUE_A = "360:00:00.00000"; private final String DEFAULT_VALUE_N = "00:00:00.00000N"; private final String DEFAULT_VALUE_E = "000:00:00.00000E"; private final String DEFAULT_VALUE_A = "000:00:00.00000"; private EditText mEditText; private Pattern mPattern; //纬度正则 private final static String regExNE = "(^([0-8][0-9]):([0-5][0-9]):([0-5][0-9])(\\.{1})([0-9]{5})" + "(N|S)$)|(^([0-8][0-9]):([6][0]):([0-5][0-9])(\\.{1})([0-9]{5})(N|S)$)|(^([0-8]" + "[0-9]):([0-5][0-9]):(60)(\\.{1})([0]{5})(N|S)$)|(^([0-8][0-9]):([6][0]):([6]" + "[0])(\\.{1})([0]{5})(N|S)$)|(^90:00:00.00000(N|S)$)"; //经度正则 private final static String regExEW = "(^([0][0-9][0-9]):([0-5][0-9]):([0-5][0-9])(\\.{1})([0-9]{5})(E|W)$)|(^(0[0-9]" + "[0-9]):([6][0]):([0-5][0-9])(\\.{1})([0-9]{5})(E|W)$)|(^(0[0-9][0-9]):([0-5][0-9]):(60)(\\.{1})" + "([0]{5})(E|W)$)|(^(0[0-9][0-9]):([6][0]):([6][0])(\\.{1})([0]{5})(E|W)$)|(^([1][0-7][0-9]):" + "([0-5][0-9]|60):([0-5][0-9])(\\.{1})([0-9]{5})(E|W)$)|(^([1][0-7][0-9]):([0-5][0-9]|60):" + "(60)(\\.{1})(0{5})(E|W)$)|(^180:00:00.00000(E|W)$)"; //角度正则 private final static String regEx = "(^(([0-2][0-9][0-9])|([0-3][0-5][0-9])):([0-5][0-9]|60):([0-5][0-9])(\\.{1})" + "([0-9]{5})$)|(^(([0-2][0-9][0-9])|([0-3][0-5][0-9])):([0-5][0-9]|60):(60)(\\.{1})(0{5})$)" + "|(^([0-3][0-5][0-9]):([6][0]):([0-5][0-9])(\\.{1})([0-9]{5})$)|(^([0-3][0-5][0-9]):(60):(60)" + "(\\.{1})([0]{5})$)|(^([0-3][0-5][0-9]):([0-5][0-9]):(60)(\\.{1})([0]{5})$)|(^([0-3][0-5][0-9])" + ":([0-5][0-9]):([0-5][0-9])(\\.{1})([0-9]{5})$)|(^360:00:00.00000$)"; /** * 构造方法。 * @param editText 需要控制的输入框。默认采用纬度控制,纬度最大值90:00:00.00000。 */ public DMSTextWatcher(EditText editText) { this(editText,0,null); } /** * 构造方法。 * @param editText 需要控制的输入框。 * @param type 控制方式,经度-1、纬度-0、角度-2。 * <li>0-纬度控制,纬度最大值90:00:00.00000</li> * <li>1-经度控制,经度最大值180:00:00.00000</li> * <li>2-角度控制,经度最大值360:00:00.00000</li> */ public DMSTextWatcher(EditText editText,int type) { this(editText,type,null); } /** * 构造方法。 * @param editText 需要控制的输入框。默认采用纬度控制,纬度最大值90:00:00.00000。 * @param defaultValue 默认值。 */ public DMSTextWatcher(EditText editText,String defaultValue) { this(editText,0,defaultValue); } /** * 构造方法。 * @param editText 需要控制的输入框。 * @param type 控制方式,经度-1、纬度-0、角度-2。 * <li>0-纬度控制,纬度最大值90:00:00.00000</li> * <li>1-经度控制,经度最大值180:00:00.00000</li> * <li>2-角度控制,经度最大值360:00:00.00000</li> * @param defaultValue 默认值。 */ public DMSTextWatcher(EditText editText,int type,String defaultValue) { this.mEditText = editText; watchType = type; if(watchType == 0){ this.mPattern = Pattern.compile(regExNE); if(defaultValue != null){ Matcher matcher = mPattern.matcher(defaultValue); if(matcher.find()){ this.mEditText.setText(defaultValue); }else{ this.mEditText.setText(DEFAULT_VALUE_N); } }else{ this.mEditText.setText(DEFAULT_VALUE_N); } }else if(watchType == 1){ this.mPattern = Pattern.compile(regExEW); if(defaultValue != null){ Matcher matcher = mPattern.matcher(defaultValue); if(matcher.find()){ this.mEditText.setText(defaultValue); }else{ this.mEditText.setText(DEFAULT_VALUE_E); } }else{ this.mEditText.setText(DEFAULT_VALUE_E); } }else if(watchType == 2){ this.mPattern = Pattern.compile(regEx); if(defaultValue != null){ Matcher matcher = mPattern.matcher(defaultValue); if(matcher.find()){ this.mEditText.setText(defaultValue); }else{ this.mEditText.setText(DEFAULT_VALUE_A); } }else{ this.mEditText.setText(DEFAULT_VALUE_A); } } } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // KLog.d("onTextChanged :"+s+" "+start+"---"+before+"---"+count); if(watchType == 0){ onNSTextChanged(s,start,before,count); }else if(watchType == 1){ onEWTextChanged(s,start,before,count); }else if(watchType == 2){ onAngleTextChanged(s,start,before,count); } } @Override public void beforeTextChanged(CharSequence s, int start, int count,int after) { // KLog.d("beforeTextChanged :"+s+" "+start+"---"+after+"---"+count); if(backspace){ oldText = new String(s.toString()); }else{ backspace = true; } } @Override public void afterTextChanged(Editable s) { // KLog.d("afterTextChanged :"+s); } private void onNSTextChanged(CharSequence s, int start, int before, int count){ StringBuilder str = new StringBuilder(s.toString()); if(oldText != null && str.length() < oldText.length()){ if(start == 2 || start == 5 || start == 8 || start == 14){ str = new StringBuilder(oldText); }else{ str.insert(start, "0"); } mEditText.setTextKeepState(str); oldText = null; }else{ Matcher m = mPattern.matcher(str); if(!m.find()){ StringBuilder oldStr = new StringBuilder(str.toString().substring(0,start)+str.substring(start+1)); if(count > 1){ str = new StringBuilder(MAX_VALUE_N); str.append(oldStr.charAt(14) == 'N'?"N":"S"); }else{ if(start == 2 || start == 5 || start == 8){ str = oldStr; }else if(start == 14 || start == 15){ start = 14; if(oldStr.charAt(14) == 'N'){ oldStr.replace(start, start+1, "S"); }else{ oldStr.replace(start, start+1, "N"); } str = oldStr; mEditText.setSelection(start); }else{ String ch = str.substring(start, start+1); str = new StringBuilder(oldStr); str = str.replace(start, start+1, ch); if(start == 0){ if(ch.equals("9")){ str = new StringBuilder(MAX_VALUE_N); str.append(oldStr.charAt(14) == 'N'?"N":"S"); } }else if(start == 3 || start == 6){ if("6789".indexOf(ch) > -1){ str = str.replace(start, start+1, "6"); str = str.replace(start+1, start+2, "0"); if(start == 6){ str = str.replace(start+3, start+8, "00000"); } } } m = mPattern.matcher(str); m.reset(); if(!m.find()){ str = oldStr; } } } backspace = false; oldText = null; mEditText.setTextKeepState(str); } } } private void onEWTextChanged(CharSequence s, int start, int before, int count){ StringBuilder str = new StringBuilder(s.toString()); if(oldText != null && str.length() < oldText.length()){ if(start == 3 || start == 6 || start == 9 || start == 15){ str = new StringBuilder(oldText); }else{ str.insert(start, "0"); } mEditText.setTextKeepState(str); oldText = null; }else{ Matcher m = mPattern.matcher(str); if(!m.find()){ StringBuilder oldStr = new StringBuilder(str.toString().substring(0,start)+str.substring(start+1)); if(count > 1){ str = new StringBuilder(MAX_VALUE_E); str.append(oldStr.charAt(15) == 'W'?"W":"E"); }else{ if(start == 3 || start == 6 || start == 9){ str = oldStr; }else if(start == 15 || start == 16){ start = 15; if(oldStr.charAt(15) == 'E'){ oldStr.replace(start, start+1, "W"); }else{ oldStr.replace(start, start+1, "E"); } str = oldStr; mEditText.setSelection(start); }else{ String ch = str.substring(start, start+1); str = new StringBuilder(oldStr); str = str.replace(start, start+1, ch); if(start == 0){ if("23456789".indexOf(ch) > -1){ str = new StringBuilder(MAX_VALUE_E); str.append(oldStr.charAt(15) == 'W'?"W":"E"); } if("1".indexOf(ch) > -1 && (str.charAt(1) == '9' || str.charAt(1) == '8')){ str = new StringBuilder(MAX_VALUE_E); str.append(oldStr.charAt(15) == 'W'?"W":"E"); } }else if(start == 1){ if(("89").indexOf(ch) > -1 && str.charAt(0) == '1'){ str = new StringBuilder(MAX_VALUE_E); str.append(oldStr.charAt(15) == 'W'?"W":"E"); } }else if(start == 4 || start == 7){ if("6789".indexOf(ch) > -1){ str = str.replace(start, start+1, "6"); str = str.replace(start+1, start+2, "0"); if(start == 7){ str = str.replace(start+3, start+8, "00000"); } } } m = mPattern.matcher(str); m.reset(); if(!m.find()){ str = oldStr; } } } backspace = false; oldText = null; mEditText.setTextKeepState(str); } } } private void onAngleTextChanged(CharSequence s, int start, int before, int count){ StringBuilder str = new StringBuilder(s.toString()); if(oldText != null && str.length() < oldText.length()){ if(start == 3 || start == 6 || start == 9 || start == 15){ str = new StringBuilder(oldText); }else{ str.insert(start, "0"); } mEditText.setTextKeepState(str); oldText = null; }else{ Matcher m = mPattern.matcher(str); if(!m.find()){ StringBuilder oldStr = new StringBuilder(str.toString().substring(0,start)+str.substring(start+1)); if(count > 1){ str = new StringBuilder(MAX_VALUE_A); }else{ if(start == 3 || start == 6 || start == 9){ str = oldStr; }else if(start == 15){ start = 15; str = oldStr; mEditText.setSelection(start); }else{ String ch = str.substring(start, start+1); str = new StringBuilder(oldStr); str = str.replace(start, start+1, ch); if(start == 0){ if("456789".indexOf(ch) > -1){ str = new StringBuilder(MAX_VALUE_A); } if("3".indexOf(ch) > -1 && ("6789".indexOf(str.charAt(1)) > -1)){ str = new StringBuilder(MAX_VALUE_A); } }else if(start == 1){ if(("6789").indexOf(ch) > -1 && str.charAt(0) == '3'){ str = new StringBuilder(MAX_VALUE_A); } }else if(start == 4 || start == 7){ if("6789".indexOf(ch) > -1){ str = str.replace(start, start+1, "6"); str = str.replace(start+1, start+2, "0"); if(start == 7){ str = str.replace(start+3, start+8, "00000"); } } } m = mPattern.matcher(str); m.reset(); if(!m.find()){ str = oldStr; } } } backspace = false; oldText = null; mEditText.setTextKeepState(str); } } } }
我实现了三种类型的现在,分别对应纬度、经度和角度,在构造方法里通过参数判断,使用也很简单
EditView editView = findViewById(R.id.editView); editView.addTextChangedListener(new DMSTextWatcher(editView,0));
后来发现有个InputFilter接口似乎也能实现这个效果,时间有限,以后有空再研究。
相关文章推荐
- 直接双击启动tomcat中的startup.bat闪退原因及解决方法
- java定时器配置
- sh 循环
- jvm虚拟机的故事之(我是一个Java class)
- 正确使用Java的foreach语句
- Tomcat内存溢出的原因--Exception in thread “RMI TCP Connection(idle)” ---OutOfMemoryError: PermGen space
- angularjs 本地数据存储LocalStorage
- n internal error occurred during: "Launching portal on Tomcat 7.x (1)". java.lang.NullPointerExcept
- Linux内核分析课程总结
- JavaScript实现显示函数调用堆栈的方法
- 83. Remove Duplicates from Sorted List
- 118.Pascal's Triangle
- awk-4
- Redis 设置密码登录
- 死理性派是怎样判断漂亮女孩是不是单身的?
- openssl 证书请求和自签名命令 req 详解
- 如何获取APP上面的所有图片(iOS Images Extractor)
- 使用Loadrunner进行文件的上传和下载
- Android开发中libs包下面的mips、armeabi、armeabi-v7a和x86
- 三阶魔方自动还原 vc实现