package com.yidian.AddSpaceEditText;

import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import android.widget.EditText; /**
* Created by bmc on 2018/4/13.
*/ public class AddSpaceTextWatcher implements TextWatcher { /** text改变之前的长度 */
private int beforeTextLength = 0;
private int onTextLength = 0;
private boolean isChanged = false;
private StringBuffer buffer = new StringBuffer();
/** 改变之前text空格数量 */
int spaceNumberA = 0;
private EditText editText;
/** text最大长度限制 */
private int maxLenght;
private SpaceType spaceType;
/** 记录光标的位置 */
private int location = 0;
/** 是否是主动设置text */
private boolean isSetText = false; public AddSpaceTextWatcher(EditText editText, int maxLenght) {
this.editText = editText;
this.maxLenght = maxLenght;
if (editText == null) {
new NullPointerException("editText is null");
}
spaceType = SpaceType.defaultType;
editText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(
maxLenght) });
editText.addTextChangedListener(this);
} @Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
beforeTextLength = s.length();
if (buffer.length() > 0) {
buffer.delete(0, buffer.length());
}
spaceNumberA = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ') {
spaceNumberA++;
}
}
} @Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
onTextLength = s.length();
buffer.append(s.toString());
if (onTextLength == beforeTextLength || onTextLength > maxLenght
|| isChanged) {
isChanged = false;
return;
}
isChanged = true;
} @Override
public void afterTextChanged(Editable s) {
if (isChanged) {
location = editText.getSelectionEnd();
int index = 0;
while (index < buffer.length()) { // 删掉所有空格
if (buffer.charAt(index) == ' ') {
buffer.deleteCharAt(index);
} else {
index++;
}
} index = 0;
int spaceNumberB = 0;
while (index < buffer.length()) { // 插入所有空格
spaceNumberB = insertSpace(index, spaceNumberB);
index++;
} String str = buffer.toString(); // 下面是计算光位置的
if (spaceNumberB > spaceNumberA) {
location += (spaceNumberB - spaceNumberA);
spaceNumberA = spaceNumberB;
}
if (isSetText) {
location = str.length();
isSetText = false;
} else if (location > str.length()) {
location = str.length();
} else if (location < 0) {
location = 0;
}
updateContext(s,str);
isChanged = false;
}
} /**
* 更新编辑框中的内容
*
* @param editable
* @param values
*/
private void updateContext(Editable editable,String values) {
if (spaceType == SpaceType.IDCardNumberType) {
editable.replace(0, editable.length(), values);
}else{
editText.setText(values);
try {
editText.setSelection(location);
} catch (Exception e) {
e.printStackTrace();
}
}
} /**
* 根据类型插入空格
*
* @param index
* @param spaceNumberAfter
* @return
* @see [类、类#方法、类#成员]
*/
private int insertSpace(int index, int spaceNumberAfter) {
switch (spaceType) {
case defaultType:// 相隔四位空格
if (index > 3
&& (index % (4 * (spaceNumberAfter + 1)) == spaceNumberAfter)) {
buffer.insert(index, ' ');
spaceNumberAfter++;
}
break;
case bankCardNumberType:
if (index > 3
&& (index % (4 * (spaceNumberAfter + 1)) == spaceNumberAfter)) {
buffer.insert(index, ' ');
spaceNumberAfter++;
}
break;
case mobilePhoneNumberType:
if (index == 3
|| ((index > 7) && ((index - 3) % (4 * spaceNumberAfter) == spaceNumberAfter))) {
buffer.insert(index, ' ');
spaceNumberAfter++;
}
break;
case IDCardNumberType:
if (index == 6
|| ((index > 10) && ((index - 6) % (4 * spaceNumberAfter) == spaceNumberAfter))) {
buffer.insert(index, ' ');
spaceNumberAfter++;
}
break;
default:
if (index > 3
&& (index % (4 * (spaceNumberAfter + 1)) == spaceNumberAfter)) {
buffer.insert(index, ' ');
spaceNumberAfter++;
}
break;
}
return spaceNumberAfter;
} /***
* 计算需要的空格数
*
* @return 返回添加空格后的字符串长度
* @see [类、类#方法、类#成员]
*/
private int computeSpaceCount(CharSequence charSequence) {
buffer.delete(0, buffer.length());
buffer.append(charSequence.toString());
int index = 0;
int spaceNumberB = 0;
while (index < buffer.length()) { // 插入所有空格
spaceNumberB = insertSpace(index, spaceNumberB);
index++;
}
buffer.delete(0, buffer.length());
return index;
} /**
* 设置空格类型
*
* @param spaceType
* @see [类、类#方法、类#成员]
*/
public void setSpaceType(SpaceType spaceType) {
this.spaceType = spaceType;
if (this.spaceType == SpaceType.IDCardNumberType) {
editText.setInputType(InputType.TYPE_CLASS_TEXT); //此处添加输入法的限制
String digits = "0123456789Xx ";
if(!TextUtils.isEmpty(digits)) {
editText.setKeyListener(DigitsKeyListener.getInstance(digits));
}
}
} /**
* 设置输入字符
*
* @param charSequence
* @return 返回设置成功失败
* @see [类、类#方法、类#成员]
*/
public boolean setText(CharSequence charSequence) {
if (editText != null && !TextUtils.isEmpty(charSequence) && computeSpaceCount(charSequence) <= maxLenght) {
isSetText = true;
editText.removeTextChangedListener(this);
editText.setText(charSequence);
editText.addTextChangedListener(this);
return true;
}
return false;
} /**
* 得到输入的字符串去空格后的字符串
*
* @return
* @see [类、类#方法、类#成员]
*/
public String getTextNotSpace() {
if (editText != null) {
return delSpace(editText.getText().toString());
}
return null;
} /**
* 得到输入的字符串去空格后的长度
*
* @return
* @see [类、类#方法、类#成员]
*/
public int getLenghtNotSpace() {
if (editText != null) {
return getTextNotSpace().length();
}
return 0;
} /**
* 得到空格数量
*
* @return
* @see [类、类#方法、类#成员]
*/
public int getSpaceCount() {
return spaceNumberA;
} /**
* 去掉字符空格,换行符等
*
* @param str
* @return
* @see [类、类#方法、类#成员]
*/
private String delSpace(String str) {
if (str != null) {
str = str.replaceAll("\r", "");
str = str.replaceAll("\n", "");
str = str.replace(" ", "");
}
return str;
}
/**
* 空格类型
*/
public enum SpaceType {
/** 默认类型 */
defaultType,
/** 银行卡类型 */
bankCardNumberType,
/** 手机号类型 */
mobilePhoneNumberType,
/** 身份证类型 */
IDCardNumberType;
} }

具体的用法

public class MainActivity extends AppCompatActivity {
private AddSpaceTextWatcher[] asEditTexts=new AddSpaceTextWatcher[3];
private EditText[] editTexts=new EditText[3];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTexts[0]=(EditText)findViewById(R.id.editText);//银行卡
editTexts[1]=(EditText)findViewById(R.id.editText2);//手机号
editTexts[2]=(EditText)findViewById(R.id.editText3);//身份证
asEditTexts[0]=new AddSpaceTextWatcher(editTexts[0],48);
asEditTexts[0].setSpaceType(AddSpaceTextWatcher.SpaceType.bankCardNumberType);
asEditTexts[1]=new AddSpaceTextWatcher(editTexts[1],13);
asEditTexts[1].setSpaceType(AddSpaceTextWatcher.SpaceType.mobilePhoneNumberType);
asEditTexts[2]=new AddSpaceTextWatcher(editTexts[2],21);
asEditTexts[2].setSpaceType(AddSpaceTextWatcher.SpaceType.IDCardNumberType);
}
}

在布局文件中的使用

<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.robin.lazy.text.MainActivity"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="@+id/textView" /> <EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:singleLine="true"
android:id="@+id/editText"
android:hint="银行卡类型"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" /> <EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:singleLine="true"
android:hint="手机号类型"
android:id="@+id/editText2"
android:layout_below="@+id/editText"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="45dp" /> <EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberSigned"
android:singleLine="true"
android:hint="身份证类型"
android:id="@+id/editText3"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>

银行卡号、电话号、身份证号 EditText 自定义格式的输入框的更多相关文章

  1. python 【pandas】账号、银行卡号、身份证号导出文件后以科学计数法显示问题解决

    问题描述:excel表中的一些数据会以文本格式格式保存,例如一些较长的编号.银行账号.身份证号等,再python中导出文件后,会发现数据以科学计数法显示,影响后续使用. data2_3.to_exce ...

  2. Android 基于身份证号的自定义键盘

    上图上代码 public class MainActivity extends AppCompatActivity { EditText writebankcard_mobileedit; Custo ...

  3. js 随机生成姓名、手机号、身份证号、银行卡号

    开发测试的时候,经常需要填写姓名.手机号.身份证号.银行卡号,既要符合格式要求.又不能重复.大家会到网上搜各种生成器.能不能自己写一个简单的生成器呢.下面是随机生成姓名.手机号.身份证号.银行卡号的j ...

  4. juqery 判断所有input 不能为空 判断只能为数字 判断身份证号:18位和15位 判断是否银行卡号

    //jq 判断某字符串是否含有特殊符号 function CheckNum() { //定义数组保存特殊字符 var AllNumIsSame = new Array("’", & ...

  5. JavaScript正则验证数字、英文、电话号、身份证号、邮箱地址、链接地址等

    验证是否为数字:/^[0-9]*$/验证是否为汉字:/^[\u4e00-\u9fa5],{0,}$/验证x-y位的数字:/^\d{x,y}$/验证由26个英文字母组成的字符串:/^[A-Za-z]+$ ...

  6. 最全,可直接用的一些正则校验,判断邮箱,手机号码,车牌号,身份证号,网址,账号,密码,ip,去掉html格式,工商税号等。

    一些正则校验,判断邮箱,手机号码,车牌号,身份证号,网址,账号,密码,ip,去掉html格式,工商税号等. // 判断邮箱 isValid = [text isValidEmail]; // 判断手机 ...

  7. 关于导出csv格式文件的身份证号、日期的处理

    EXCEL系统的单元格,默认格式是常规或数值格式下,数字超过10位即以科学计数法显示,对15位以后的数字用0填充. 在导入到Excel.导出csv文件时,对于身份证号自动变成科学计数法的地方,就要做一 ...

  8. bootstrap-validator基本使用(自定义验证身份证号和手机号)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  9. 基于struts2框架-自定义身份证号验证器

    自定义拦截器的步骤: 1.定义一个验证器的类: > 自定义的验证器都需要实现 Validator接口.  > 可以选择继承 ValidatorSupport 或 FieldValidato ...

随机推荐

  1. 【Linux学习笔记】关于ubuntu开机菜单栏和任务栏不见了的有效解决方法

    (一) 问题描述 ubuntu开机只有桌面,没有菜单栏和任务栏,如下图: (二) 问题解决 刚学习ubuntu,总有些像我这样不折腾就不舒服的人,今天改了一下主题,图标什么的,重启开机后就发现!咦!我 ...

  2. 校招:Vobile阜博通2015校园招聘

    关于Vobile阜博通校招(10-11月份),耗时将近一个月,现整理分享给大家. 1 浙大笔试无选择填空,问答题为主,偏语言的个人理解,不在意具体语言方向(C/C++/Java).(1)描述C.C++ ...

  3. 【UML 建模】UML建模语言入门 -- 用例视图详解 用例视图建模实战

    . 作者 :万境绝尘  转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . 一. 用例视图概述 用例视图表述哪些 ...

  4. FNDCPASS Troubleshooting Guide For Login and Changing Applications Passwords

    In this Document   Goal   Solution   1. Error Starting Application Services After Changing APPS Pass ...

  5. 系统性能监测(使用nmon、nmonanalyser)

    系统性能监测使用工具: l系统性能监测使用的主要监测工具是:nmon(AIX6.1及以上版本系统自带). l系统性能监测使用的主要分析工具是:nmonanalyser. NMON工具简介: NMON工 ...

  6. 50行代码实现的一个最简单的基于 DirectShow 的视频播放器

    本文介绍一个最简单的基于 DirectShow 的视频播放器.该播放器对于初学者来说是十分有用的,它包含了使用 DirectShow 播放视频所有必备的函数. 直接贴上代码,具体代码的含义都写在注释中 ...

  7. MongoDB 3.0新增特性一览

    转自:http://blog.sina.com.cn/s/blog_48c95a190102vedr.html 引言 在历经版本号修改(2.8版本直接跳到3.0版本)和11个rc版本之后,MongoD ...

  8. 【Qt编程】基于Qt的词典开发系列<十五>html特殊字符及正则表达式

    1.html特殊字符的显示 我们知道html语言和C语言一样也有一些特殊字符,它们是不能正常显示的,必须经过转义,在网上可以查到如何显示这些字符,如下图所示: 上图给了最常用的特殊字符的显示,下面我们 ...

  9. 基于Bresenham和DDA算法画线段

    直线:y=kx+b 为了将他在显示屏上显示出来,我们需要为相应的点赋值,那么考虑到计算机的乘法执行效率,我们肯定不会选择用Y=kx+b这个表达式求值,然后进行画线段. 我们应当是将它转化为加法运算. ...

  10. C语言算法---求鞍点

    题目:有一个3X4矩阵,要求输出其鞍点(行列均最大的值),以及它的行号和列号. int a[3][4] = {{123,94,-10,218},                          {3 ...