回复
EditText输入内容拦截和监听删除
hackernew
发布于 2021-2-26 10:30
浏览
0收藏
前言
有时候我们会有一些特殊的需求,需要对输入框进行特殊的处理,比如:
- 对输入内容去除特殊字符操作,或拦截输入内容提交
- 监听软件盘删除按钮点击事件,并能在一定条件下拦截
- 监听输入框文字粘贴、复制、全选等
拦截输入内容提交
对于 EditText 的文字监听,我们通常使用的是添加文字变化监听 addTextChangedListener(watcher) ,通过文字变化监听 TextWatcher 对文字作处理,处理后重新设置文字。需要处理死循环的问题(类似递归,要有终止条件)。
其实可以在输入文字提交之前,还未显示到界面时,就对文字进行处理,需要重写方法
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new MyInputConnection(super.onCreateInputConnection(outAttrs), false);
}
创建自己的输入连接(InputConnection),在 commitText() 方法中返回 false,提交的内容将会被拦截。
具体代码见最后。
监听软件盘删除按钮点击事件
对于软键盘删除按键的监听,通常我们使用 setOnKeyListener(l) ,但是在一些非常规特殊情况下不那么好用,比如多行输入时屏蔽换行。
监听输入框文字粘贴、复制、全选等
监听输入框文字粘贴、复制、全选等操作,需要重写 onTextContextMenuItem(id) 方法,通过 id 区分操作,重写对应的逻辑。都有哪些操作,也即都有哪些 id 呢?ctrl + 鼠标左键点击 super.onTextContextMenuItem(id) ,查看源码,找到了以下 id:
* static final int ID_SELECT_ALL = android.R.id.selectAll;
* static final int ID_UNDO = android.R.id.undo;
* static final int ID_REDO = android.R.id.redo;
* static final int ID_CUT = android.R.id.cut;
* static final int ID_COPY = android.R.id.copy;
* static final int ID_PASTE = android.R.id.paste;
* static final int ID_SHARE = android.R.id.shareText;
* static final int ID_PASTE_AS_PLAIN_TEXT = android.R.id.pasteAsPlainText;
* static final int ID_REPLACE = android.R.id.replaceText;
* static final int ID_ASSIST = android.R.id.textAssist;
* static final int ID_AUTOFILL = android.R.id.autofill;
由于源码里并没有开放这些 id 常量,所以只能用 android.R.id.copy 这样的 id。
code
/**
* 扩展输入框。
* 可拦截:
* 软件盘删除按钮点击事件;
* 输入框内容提交;
* 长按文字菜单选项点击事件(复制、粘贴、全选等)
*/
public class ExtendEditText extends AppCompatEditText {
public ExtendEditText(Context context) {
super(context);
}
public ExtendEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExtendEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 监听长按后选项菜单
* @param id
* static final int ID_SELECT_ALL = android.R.id.selectAll;
* static final int ID_UNDO = android.R.id.undo;
* static final int ID_REDO = android.R.id.redo;
* static final int ID_CUT = android.R.id.cut;
* static final int ID_COPY = android.R.id.copy;
* static final int ID_PASTE = android.R.id.paste;
* static final int ID_SHARE = android.R.id.shareText;
* static final int ID_PASTE_AS_PLAIN_TEXT = android.R.id.pasteAsPlainText;
* static final int ID_REPLACE = android.R.id.replaceText;
* static final int ID_ASSIST = android.R.id.textAssist;
* static final int ID_AUTOFILL = android.R.id.autofill;
* @return
*/
@Override
public boolean onTextContextMenuItem(int id) {
boolean handled = false;
if (mOnTextMenuItemClickListener != null) {
handled = mOnTextMenuItemClickListener.onTextMenuItemClick(id);
}
return handled || super.onTextContextMenuItem(id);
}
private OnTextMenuItemClickListener mOnTextMenuItemClickListener;
/**
* 设置文字菜单选项点击监听,用于监听粘贴、全选、复制等操作,可以重写这些操作逻辑。
*/
public void setOnTextMenuItemClickListener(OnTextMenuItemClickListener onTextMenuItemClickListener) {
mOnTextMenuItemClickListener = onTextMenuItemClickListener;
}
/**
* 文字菜单选项点击监听
*/
public interface OnTextMenuItemClickListener {
boolean onTextMenuItemClick(int id);
}
/**
* 输入法
*
* @param outAttrs
* @return
*/
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new MyInputConnection(super.onCreateInputConnection(outAttrs), false);
}
private int count;
class MyInputConnection extends InputConnectionWrapper implements
InputConnection {
public MyInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}
/**
* 对输入的内容进行拦截
*
* @param text
* @param newCursorPosition
* @return
*/
@Override
public boolean commitText(CharSequence text, int newCursorPosition) {
if (mOnCommitTextListener != null) {
if (!mOnCommitTextListener.onCommitText(text, newCursorPosition)) {
return false;
}
}
// // 只能输入汉字
// if (!text.toString().matches("[\u4e00-\u9fa5]+") && !text.toString().matches("[a-zA-Z]+") && !text.toString().matches("[0-9]")) {
// ToastUtil.ToastShow(getContext(), "只能输入数字和字母和汉字");
// return false;
// }
//
//
// tips(text.toString());
//
// if (count > 16) {
// ToastUtil.ToastShow(getContext(), "最多16个字符");
// return false;
// }
return super.commitText(text, newCursorPosition);
}
private void tips(String append) {
count = 0;
String text = getText().toString();
for (int i = 0; i < text.length(); i++) {
String a = String.valueOf(text.charAt(i));
if (a.matches("[\u4e00-\u9fa5]+")) {
count = count + 2;
} else {
count = count + 1;
}
}
for (int i = 0; i < append.length(); i++) {
String a = String.valueOf(append.charAt(i));
if (a.matches("[\u4e00-\u9fa5]+")) {
count = count + 2;
} else {
count = count + 1;
}
}
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
if (mOnCommitTextListener != null) {
if (mOnCommitTextListener.onDeleteClick()) { // 软键盘删除按钮点击事件拦截。
return true;
}
}
}
return super.sendKeyEvent(event);
}
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
if (beforeLength == 1 && afterLength == 0) {
return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_DEL))
&& sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_DEL));
}
return super.deleteSurroundingText(beforeLength, afterLength);
}
}
private OnCommitTextListener mOnCommitTextListener;
public void setOnCommitTextListener(OnCommitTextListener onCommitTextListener) {
mOnCommitTextListener = onCommitTextListener;
}
public interface OnCommitTextListener {
/**
* 输入文字监听回调。可以对输入文字进行拦截,处理后再显示(比如去掉特殊字符)。
* @param text
* @param newCursorPosition
* @return
*/
boolean onCommitText(CharSequence text, int newCursorPosition);
/**
* 当软键盘删除按钮点击时的回调方法。
* @return true,拦截;false,默认
*/
boolean onDeleteClick();
}
}
分类
已于2021-2-26 10:30:07修改
赞
收藏
回复
相关推荐