android EditText输入框如何实现文字的输入长度控制呢,达到这种需求的有很多种方法;
第一种:那就是直接在XML布局代码里面设置:
<EditText
android:id="@+id/et_suggestion"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="40"
android:minHeight="100dp"
/>
第二种,利用 TextWatcher 进行监听
mEditText.addTextChangedListener(new TagNameTextWatch(mEditText),40);
。。。。。。。
。。。。。。。
//TagNameTextWatch 可以直接写成内部类
class TagNameTextWatch implements TextWatcher {
private EditText et;
private int maxLenth;
TagNameTextWatch(EditText et,int maxLenth) {
this.maxLenth = et;
this.et = et; }
@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) {
Editable editable = et.getText();
int len = editable.length();
if(len > maxLen)
{
int selEndIndex = Selection.getSelectionEnd(editable);
String str = editable.toString();
//截取新字符串
String newStr = str.substring(0,maxLen);
editText.setText(newStr);
editable = editText.getText();
//新字符串的长度
int newLen = editable.length();
//旧光标位置超过字符串长度
if(selEndIndex > newLen)
{
selEndIndex = editable.length();
}
//设置新光标所在的位置
Selection.setSelection(editable, selEndIndex);
}
}
}
第三种就是用到了InputFilter实现;
网上查到有些人会直接这样写来实现字数输入的控制:
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(40)});
上面的代码是能实现基本的字数控制,当如果加上以下别的需求,比如在输入超过40个字节是给予用户提示;那么下面我们就来吧InputFilter进行封装下;
先写一个EditTextLengthFilter类来继承InputFilter
在Activity里面执行mEditText.setFilters(newInputFilter[]{newEditTextLengthFilter(this,40,mEditText)});
下面是EditTextLengthFilter 的代码:
public class EditTextLengthFilter implements InputFilter {
private int maxLength;// 最大英文/数字长度 一个汉字算两个字母
private Context mContext;
/**
* unicode编码,判断是否为汉字(中文汉字区间)
*/
String regEx = "[\\u4e00-\\u9fa5]";
private String mToast;
private TextView tvShowNum;
/**
* 标示是单数还是双数
*/
private boolean isMupli = false;
/**
* 设置文本框最大输入长度
*
* @param context 上下文
* @param length 最大长度(备注:字符长度为应为英文长度)
* @param toast 提示语
* @param showNum 显示文字变化的TextView
*/
public EditTextLengthFilter(Context context, int length, TextView showNum, String toast) {
init(context, length, toast, showNum, null);
}
/**
* 初始化EditText必要参数
*
* @param context 上下文
* @param length 最大长度(备注:字符长度为应为英文长度,单数不处理,双数 /2 )
* @param toast 提示语
* @param showNum 显示文字变化的TextView
* @param editTextLengthChangeListener 文字变化的监听
*/
private void init(Context context, int length, String toast, TextView showNum, EditTextLengthChangeListener editTextLengthChangeListener) {
mContext = context;
isMupli = length % 2 == 0;
maxLength = isMupli ? length / 2 : length;
mToast = toast != null ? toast : "输入文字超过最大长度";
tvShowNum = showNum;
}
/**
* @param source 新输入的字符串
* @param start 新输入的字符串起始下标,一般为0
* @param end 新输入的字符串终点下标,一般为source长度-1
* @param dest 输入之前文本框内容
* @param dStart 原内容起始坐标,一般为0
* @param dEnd 原内容终点坐标,一般为dest长度-1
* @return 返回输入的字符
*/
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dStart, int dEnd) {
// 计算原始长度
int destCount = getLength(dest.toString());
// 计算原始长度是否会改变
boolean changeLength = dEnd - dStart != 0 && end - start != 0;
int deleteLength = 0;
if (changeLength ){
// 说明文字会被替换,需要计算替换长度
String sub = dest.subSequence(dStart,dEnd).toString();
deleteLength = getLength(sub);
}
// 计算输入长度
int sourceCount = getLength(source.toString());
// 判断添加文字之后长度 initLength 为 不做处理的长度
int initLength = destCount + sourceCount - deleteLength;
int length = isMupli ? (initLength + 1) / 2 : initLength;
if (length > maxLength) {
// 多余部分显示可以显示数据
int overSize = isMupli ? 2 * maxLength - (destCount - deleteLength) : maxLength - (destCount - deleteLength);
String overContent = "";
if (sourceCount != 0 ) {
int subSize = getLength(source.toString(), overSize);
if (subSize > 0) {
overContent = source.subSequence(0, subSize).toString();
}
}
if (!TextUtils.isEmpty(mToast)) {
ToastUtil.showTextViewPrompt(AppContextUtils.getAppContext(), mToast);
}
operator(maxLength);
return overContent;
} else {
int d = dEnd - dStart;
// 说明是在删除文字
if (d > 0 && length > 0 && start == 0 && end == 0) {
// 说明是全部删除英文字母 && 说明是全部删除中文字母
if (d == destCount || d == dest.length()) {
length = 0;
} else {
// sourceCount 字符长度如果为0 则说明在删除文字
if (sourceCount == 0) {
int sub = getLength(dest.subSequence(dStart, dEnd).toString());
if (sub > 1) {
length = length - (sub + 1) / 2;
} else if (sub == 1) {
if (destCount % 2 != 0) {
length = length - 1;
}
}
}
}
}
operator(length);
return source;
}
}
/**
这里显示我们平时看到的12/40的需求,
*/
private void operator(int length) {
if (tvShowNum != null) {
String num = length + "/" + maxLength;
tvShowNum.setText(num);
}
}
/**
* 计算字符长度 中文算两个
*
* @param str 原始字符长度
* @return 返回总长度
*/
private int getLength(String str) {
int count = str.length();
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
while (m.find()) {
for (int i = 0; i <= m.groupCount(); i++) {
count = count + 1;
}
}
return count;
}
/**
* 获取可以显示的长度
*
* @param str 待截取文本
* @param maxLength 可以显示的大小
* @return 返回截取文本的长度
*/
private int getLength(String str, int maxLength) {
// 对于用户显示的长度
int count = 0;
// 实际字节的长度
int cutIndex = 0;
if (maxLength > 0) {
char[] currentCh = str.toCharArray();
for (char c : currentCh) {
if (c >= 0x4e00 && c <= 0x9fbb) {
// 中文加2个
count = count + 2;
} else {
count++;
}
if (count > maxLength) {
return cutIndex;
}
cutIndex++;
}
}
return cutIndex;
}
上面EditTextLengthFilter 重写了InputFilter 里面的filter方法,里面有比较清楚的截取文字长度的逻辑,大家需要细看;