/**
* @author :
* @date:2018/12/18
*/
public class CEditText extends EditText {
private static final String DEFAULT_MAX_MONEY_VALUE = \"^[\\\\d]{1,numSize}([.][\\\\d]{0,maxDecimalSize})?$\";
private static final String DEFAULT_LIMIT_DECIMAL = \"^[\\\\d]([.][\\\\d]{0,maxDecimalSize})?$\";
private static final String DEFAULT_LIMIT_NUM = \"^[\\\\d]{1,numSize}([.][\\\\d])?$\";
/**
* 汉字正则表达式
*/
private static final String CHINE_SWORD = \"^[\\\\u4e00-\\\\u9fa5]+$\";
/**
* 换行回车正则表达式
*/
public static final String ENTER_REGEX = \"(.*((\\\\r+)|(\\\\n+)|(\\\\r\\\\n)+|(\\\\n\\\\r)+).*)\";
/**
* 邮箱
*/
public static final String EMAIL_REGEX =
\"^[a-zA-Z0-9][\\\\w\\\\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\\\\w\\\\.-]*[a-zA-Z0-9]\\\\.[a-zA-Z][a-zA-Z\\\\.]*[a-zA-Z]$\";
/**
* 空格正则表达式
*/
public static final String SPACE_REGEX = \" \";
/**
* 字母和数字正则表达式
*/
public static final String EN_NUMBER = \"^[A-Za-z0-9]$\";
/**
* 身份证
*/
public static final String ID_CARD_REG = \"^(\\\\d{15}$|^\\\\d{18}$|^\\\\d{17}(\\\\d|X|x))$\";
/**
* 手机号码
*/
public static final String PHONE_REGEX = \"^(1[3456789][0-9]{9})$\";
//中文和点
public static final String REGEX_CHINESE_NAME = \"^[•·..\\\\u4e00-\\\\u9fa5]+$\";
/**
* 中文,数字和英文
*/
public static final String REGEX_ZH_NB_EN = \"^[A-Za-z0-9\\\\u4e00-\\\\u9fa5]+$\";
private boolean isOnlyInputNumber; //只能输入整数
private boolean isOnlyInputDecimal; //输入整数和小数
private boolean isOnlyInputChinese; //只能中文
private boolean isOnlyInputNumEn; //只能输入数字和英文
private boolean isOnlyInputEmail;
private boolean isOnlyInputPhone;
private boolean isOnlyInputIdCard;
private boolean isOnlyInputChinesed;
private boolean isOnlyInputChEnNum;
private int maxNumberSize; //整数部分最大位数
private int maxDecimalSize; //小数部分最大位数
private int maxInputSize; //输入的最大长度
private boolean canInputSpace;
private boolean canInputEnter;
private boolean canInputEmoji;
private List<InputFilter> inputFilters;
public CEditText(Context context) {
super(context);
}
public CEditText(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CEditText);
init(array);
}
public CEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CEditText);
init(array);
}
private void init(TypedArray arrays) {
isOnlyInputNumber = arrays.getBoolean(R.styleable.CEditText_isOnlyInputNumber, false);
isOnlyInputDecimal = arrays.getBoolean(R.styleable.CEditText_isOnlyInputDecimal, false);
isOnlyInputChinese = arrays.getBoolean(R.styleable.CEditText_isOnlyInputChinese, false);
isOnlyInputNumEn = arrays.getBoolean(R.styleable.CEditText_isOnlyInputNumEn, false);
isOnlyInputEmail = arrays.getBoolean(R.styleable.CEditText_isOnlyInputEmail, false);
isOnlyInputPhone = arrays.getBoolean(R.styleable.CEditText_isOnlyInputPhone, false);
isOnlyInputIdCard = arrays.getBoolean(R.styleable.CEditText_isOnlyInputIdCard, false);
isOnlyInputChinesed = arrays.getBoolean(R.styleable.CEditText_isOnlyInputChinesed, false); //中文加点
isOnlyInputChEnNum = arrays.getBoolean(R.styleable.CEditText_isOnlyInputChEnNum, false); //中文英文加数字
maxNumberSize = arrays.getInt(R.styleable.CEditText_maxNumberSize, 0);
maxDecimalSize = arrays.getInt(R.styleable.CEditText_maxDecimalSize, 0);
maxInputSize = arrays.getInt(R.styleable.CEditText_maxInputSize, 0);
canInputSpace = arrays.getBoolean(R.styleable.CEditText_canInputSpace, false);
canInputEnter = arrays.getBoolean(R.styleable.CEditText_canInputEnter, false);
canInputEmoji = arrays.getBoolean(R.styleable.CEditText_canInputEmoji, false);
inputFilters = new ArrayList<>();
if (isOnlyInputNumber) { //只能输入数字
setInputType(InputType.TYPE_CLASS_NUMBER);
if (maxInputSize > 0) {//限制长度
inputFilters.add(new InputFilter.LengthFilter(maxInputSize));
}
} else if (isOnlyInputDecimal) {//只能输入小数
setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
if (maxInputSize > 0) { //限制长度
inputFilters.add(new InputFilter.LengthFilter(maxInputSize));
}
} else if (isOnlyInputChinese) {//只能输入中文
inputFilters.add(new RegexResultFilter(CHINE_SWORD));
if (maxInputSize > 0) { //限制长度
inputFilters.add(new InputFilter.LengthFilter(maxInputSize));
}
} else if (isOnlyInputNumEn) { //英文和数字
inputFilters.add(new RegexResultFilter(EN_NUMBER));
if (maxInputSize > 0) { //限制长度
inputFilters.add(new InputFilter.LengthFilter(maxInputSize));
}
} else if (isOnlyInputEmail) { //邮箱验证
inputFilters.add(new RegexResultFilter(EMAIL_REGEX));
} else if (isOnlyInputPhone) { //1[3456789]开始的手机号码
inputFilters.add(new RegexResultFilter(PHONE_REGEX));
} else if (isOnlyInputIdCard) { //身份证号码
inputFilters.add(new RegexResultFilter(ID_CARD_REG));
} else if (isOnlyInputChinesed) { //中文和·
inputFilters.add(new RegexResultFilter(REGEX_CHINESE_NAME));
if (maxInputSize > 0) { //限制长度
inputFilters.add(new InputFilter.LengthFilter(maxInputSize));
}
} else if (isOnlyInputChEnNum) { //中文英文和数字
inputFilters.add(new RegexResultFilter(REGEX_ZH_NB_EN));
if (maxInputSize > 0) { //限制长度
inputFilters.add(new InputFilter.LengthFilter(maxInputSize));
}
} else if (maxNumberSize > 0 && maxDecimalSize > 0) {
String regex = DEFAULT_MAX_MONEY_VALUE;
regex = regex.replaceAll(\"numSize\", maxNumberSize + \"\").replaceAll(\"maxDecimalSize\", maxDecimalSize + \"\");
//限制整数部分或者小数部分的长度
inputFilters.add(new RegexResultFilter(regex));
} else if (maxNumberSize > 0 && maxDecimalSize <= 0) {
String regex = DEFAULT_LIMIT_NUM;
regex = regex.replaceAll(\"numSize\", maxNumberSize + \"\");
inputFilters.add(new RegexResultFilter(regex)); //限制整数部分或者小数部分的长度
} else if (maxNumberSize <= 0 && maxDecimalSize > 0) {
String regex = DEFAULT_LIMIT_DECIMAL;
regex = regex.replaceAll(\"maxDecimalSize\", maxDecimalSize + \"\");
inputFilters.add(new RegexResultFilter(regex)); //限制整数部分或者小数部分的长度
}
setCanInputSpaceEnterEmoji(inputFilters);
setDefaultFilers(inputFilters);
}
/**
* 是否可以输入表情,空格,回车
*
* @param inputFilters
*/
private void setCanInputSpaceEnterEmoji(List<InputFilter> inputFilters) {
if (!canInputEmoji) {
inputFilters.add(new InputFilterEmoji());
}
if (!canInputEnter) {
inputFilters.add(new RegexInputFilter(ENTER_REGEX, false));
}
if (!canInputSpace) {
inputFilters.add(new RegexInputFilter(SPACE_REGEX, false));
}
}
private void setDefaultFilers(List<InputFilter> inputFilters) {
if (inputFilters == null || inputFilters.isEmpty()) {
return;
}
InputFilter[] newFilters = new InputFilter[inputFilters.size()];
for (int i = 0; i < inputFilters.size(); i++) {
newFilters[i] = inputFilters.get(i);
}
setFilters(newFilters);
}
//设置用户自己需要的filter
public void setMyFilers(List<InputFilter> filters, boolean isUseDefaultFilter) {
if (isUseDefaultFilter && inputFilters != null) {
inputFilters.addAll(filters);
setDefaultFilers(inputFilters);
} else {
setDefaultFilers(filters);
}
}
public class RegexResultFilter implements InputFilter {
private static final String POINTER = \".\";
private static final String ZERO = \"0\";
final private Pattern enterPattern;
/**
* @param regex 内容正则表达式
* 如果内容和正则表达式匹配,如果是想匹配留下的内容,则显示到输入框,否则不显示到输入框
* 如果内容和正则表达式不匹配,正好与上面相反
*/
public RegexResultFilter(String regex) {
enterPattern = Pattern.compile(regex);
}
/**
* @param source 输入的文字
* @param start 输入-0,删除-0
* @param end 输入-文字的长度,删除-0
* @param dest 原先显示的内容
* @param dstart 输入-原光标位置,删除-光标删除结束位置
* @param dend 输入-原光标位置,删除-光标删除开始位置
* @return
*/
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
String destText = dest.toString();
if (enterPattern != null) {
StringBuilder stringBuilder = new StringBuilder();
if (end > 0) {
//TODO 输入 - 开始部分
stringBuilder.append(dest.subSequence(0, dstart));
//TODO 输入 - 键盘输入
stringBuilder.append(source);
//TODO 输入 - 结束部分
stringBuilder.append(dest.subSequence(dstart, dest.length()));
} else {
//TODO 删除 - 开始部分
stringBuilder.append(dest.subSequence(0, dstart));
//TODO 删除 - 结束部分
stringBuilder.append(dest.subSequence(dend, dest.length()));
}
final String result = stringBuilder.toString();
System.out.println(\"预计结果: \" + stringBuilder.toString());
//TODO 如果正则满足,返回输入内容
//TODO 如果不满足正则但是接受内容,返回输入内容
if (!POINTER.equals(source.toString()) && ZERO.equals(destText)) { //如果首位输入0,接下来只能输入小数点
return \"\";
} else if (match(source, start, end, result)) {
return source;
} else {
return \"\";
}
} else {
return source;
}
}
//TODO 匹配正则
protected boolean match(CharSequence source, int start, int end, String result) {
return enterPattern.matcher(result).matches();
}
}
public class InputFilterEmoji implements InputFilter {
Pattern emoji = Pattern.compile(\"[\\ud83c\\udc00-\\ud83c\\udfff]|[\\ud83d\\udc00-\\ud83d\\udfff]|[\\u2600-\\u27ff]\",
Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
Matcher emojiMatcher = emoji.matcher(source);
if (emojiMatcher.find()) {
return \"\";
}
return null;
}
}
public class RegexInputFilter implements InputFilter {
Pattern enterPattern = null;
boolean mExpectMatch = true;
/**
* @param regex 内容正则表达式
* @param expectMatch true 期望匹配, false 期望不匹配
* 如果内容和正则表达式匹配,如果是想匹配留下的内容,则显示到输入框,否则不显示到输入框
* 如果内容和正则表达式不匹配,正好与上面相反
*/
public RegexInputFilter(String regex, boolean expectMatch) {
enterPattern = Pattern.compile(regex);
this.mExpectMatch = expectMatch;
}
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (enterPattern != null) {
if (enterPattern.matcher(source).matches()) {
if (mExpectMatch) {
return source;
} else {
return \"\";
}
} else {
if (mExpectMatch) {
return \"\";
} else {
return source;
}
}
} else {
return source;
}
}
}
}
attrs.
增加:
<declare-styleable name=\"CEditText\">
<attr name=\"isOnlyInputNumber\" format=\"boolean\"/>
<attr name=\"isOnlyInputDecimal\" format=\"boolean\"/>
<attr name=\"isOnlyInputChinese\" format=\"boolean\"/>
<attr name=\"isOnlyInputChinesed\" format=\"boolean\"/>
<attr name=\"isOnlyInputNumEn\" format=\"boolean\"/>
<attr name=\"isOnlyInputEmail\" format=\"boolean\"/>
<attr name=\"isOnlyInputPhone\" format=\"boolean\"/>
<attr name=\"isOnlyInputIdCard\" format=\"boolean\"/>
<attr name=\"isOnlyInputChEnNum\" format=\"boolean\"/>
<attr name=\"maxNumberSize\" format=\"integer\"/>
<attr name=\"maxDecimalSize\" format=\"integer\"/>
<attr name=\"maxInputSize\" format=\"integer\"/>
<attr name=\"canInputSpace\" format=\"boolean\"/>
<attr name=\"canInputEnter\" format=\"boolean\"/>
<attr name=\"canInputEmoji\" format=\"boolean\"/>
</declare-styleable>
使用:包名注意替换
<com.fkhwl.common.widget.CEditText
android:id=\"@+id/troubleContent\"
android:layout_width=\"match_parent\"
android:layout_height=\"200dp\"
android:layout_marginBottom=\"10dp\"
android:layout_marginLeft=\"5dp\"
android:layout_marginRight=\"10dp\"
android:layout_marginTop=\"10dp\"
android:background=\"@drawable/edittext_gray_white_bg\"
android:gravity=\"top|left\"
android:paddingLeft=\"1dp\"
app:isOnlyInputPhone=\"true\" //只能输入手机号码
/>
继续阅读与本文标签相同的文章
-
QQ浏览器正孵化“用户增长团队”,解读中国浏览器行业发展趋势
2026-05-18栏目: 教程
-
Java并发系列(4)java关键字-synchronized
2026-05-18栏目: 教程
-
汇编(六)栈段、第一个汇编程序
2026-05-18栏目: 教程
-
目前Web前端就业前景如何 前端应用于哪些领域
2026-05-18栏目: 教程
-
kubernetes Service:让客户端发现pod并与之通信
2026-05-18栏目: 教程
