自定义EditText利用InputConnectionWrapper进行输入拦截
利用InputConnectionWrapper拦截内容,再提交显示到屏幕上。,在内容显示到屏幕之前,进行拦截,并根据需求修改输入内容,再显示到屏幕上。进行内容输入,输入入口的控件是。自定义EditText继承自。(1)自定义EditText。实现一些替换文本的需求。修改实现自己的需求。
一、背景介绍
我的需求是:使用系统软键盘进行内容输入,输入入口的控件是AppCompatEditText,在内容显示到屏幕之前,进行拦截,并根据需求修改输入内容,再显示到屏幕上。
二、思路
自定义EditText继承自AppCompatEditText,利用InputConnectionWrapper拦截内容,再提交显示到屏幕上。
三、实现过程
(1)自定义EditText
public class ExtendEditText extends AppCompatEditText {
private boolean isPaste = false;
public ExtendEditText(@NonNull Context context) {
super(context);
}
public ExtendEditText(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public ExtendEditText(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Nullable
@Override
public InputConnection onCreateInputConnection(@NonNull EditorInfo outAttrs) {
return new MyInputConnection(super.onCreateInputConnection(outAttrs), false);
}
class MyInputConnection extends InputConnectionWrapper implements InputConnection {
/**
* Initializes a wrapper.
*
* <p><b>Caveat:</b> Although the system can accept {@code (InputConnection) null} in some
* places, you cannot emulate such a behavior by non-null {@link InputConnectionWrapper} that
* has {@code null} in {@code target}.</p>
*
* @param target the {@link InputConnection} to be proxied.
* @param mutable set {@code true} to protect this object from being reconfigured to target
* another {@link InputConnection}. Note that this is ignored while the target is {@code null}.
*/
public MyInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}
@Override
public boolean commitText(CharSequence text, int newCursorPosition) {
Log.i("shawn", "commitText:" + text + " newCursorPosition:" + newCursorPosition);
text = "被修改了";
return super.commitText(text, newCursorPosition);
}
}
/**
* 监听菜单事件:全选、复制、粘贴
* @param id
* @return
*/
@Override
public boolean onTextContextMenuItem(int id) {
if (id == android.R.id.copy) {
Log.i("shawn", "onTextContextMenuItem 复制");
} else if (id == android.R.id.paste) {
isPaste = true;
Log.i("shawn", "onTextContextMenuItem 粘贴");
} else if (id == android.R.id.selectAll) {
Log.i("shawn", "onTextContextMenuItem 全选");
} else {
Log.i("shawn", "onTextContextMenuItem id" + id);
}
return super.onTextContextMenuItem(id);
}
public boolean isPaste() {
return isPaste;
}
}
在commitText修改实现自己的需求。
PS:onTextContextMenuItem是对菜单选项的监听
(2)利用TextWatcher实现一些替换文本的需求
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Log.i(TAG, "beforeTextChanged 内容:" + s + " 粘贴输入:"+editText.isPaste() + " start:"+start+ " count:"+count+ " after:"+after);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.i(TAG, "onTextChanged 内容:" + s + " 粘贴输入:"+editText.isPaste()+ " start:"+start+ " count:"+count);
if (editorET.isPaste()) {
// 1.获取粘贴内容
// 2.修改粘贴内容
// 3.替换粘贴内容
if (!StringUtils.isEmpty(changeStr)) {
Editable editable = editorET.getText();
if (editable != null) {
editable.replace(start, replaceEnd, changeStr);
}
}
}
}
@Override
public void afterTextChanged(Editable s) {
Log.i(TAG, "afterTextChanged 内容:" + s + " 粘贴输入:"+editText.isPaste());
}
});
四:注意事项
EditText的commitText和onTextChanged方法调用次数为什么不一致?
在Android中,EditText
是一个用于接收和显示文本内容的控件。commitText
和onTextChanged
是EditText
的两个不同的方法,用于处理文本变化的情况,但它们的调用次数可能会因为不同的操作和事件触发而不一致。
-
commitText方法:
commitText
方法是InputConnection
接口中的一个方法,用于将指定的文本插入到EditText
中。通常情况下,这个方法是由输入法(软键盘)来调用的,当用户在键盘上点击一个字符时,输入法会调用commitText
来将该字符插入到EditText
中。因此,commitText
的调用次数取决于用户的输入操作和输入法的行为。不同的输入法可能会以不同的方式调用commitText
,所以调用次数可能会有所不同。 -
onTextChanged方法:
onTextChanged
方法是TextWatcher
接口中的一个方法,用于在EditText
中的文本内容发生变化时被调用。它会在文本发生变化时(插入、删除、替换等)被触发。这意味着无论是通过用户的输入、代码中的修改,还是通过其他方式改变文本内容,都有可能触发onTextChanged
方法的调用。
因此,commitText
方法的调用次数取决于用户的输入操作和输入法的行为,而onTextChanged
方法的调用次数取决于文本内容的变化。由于两者的触发条件不同,所以它们的调用次数可能会出现不一致的情况。
如果您在特定情况下发现commitText
和onTextChanged
的调用次数不一致,可以考虑检查您的代码逻辑、输入法的行为以及对EditText
的操作,以找出导致这种不一致性的原因
更多推荐
所有评论(0)