我自己的应用程序中的Android拦截软按键-Backspace问题
作者:互联网
我有一个应用程序,需要镜像我拥有的某个Fragment中所做的每个按键.到目前为止,我正在做的是将TextWatcher附加到EditText并覆盖afterTextChanged并拉出最后一个字符(EditText将被隐藏,因此一次只能输入1个字符).
为了处理退格键,我在EditText中重写onKeyDown并使用了一种解决方案,该解决方案涉及Jellybean及以上设备的自定义BaseInputConnection(将生成的KEYCODE_DEL传递给onKeyDown-在SO上的某个位置找到了此解决方案).
我遇到的问题是,当EditText为空时,不会生成KEYCODE_DEL事件,因此我无法检测到退格键(即使它不会做任何事情).我要做的是在创建EditText时向其添加单个字符,并且当我在afterTextChanged中检测到EditText为空时,这样,如果在输入另一个字符之前按退格键,它将删除该填充字符,然后用另一个填充字符重新填充它.
但是,“填充字符”永远不会被删除.例如,实例化EditText时,它会用“ a”填充.如果按退格键,则什么也不会发生.不会从EditText中删除“ a”.
有人知道这是怎么回事吗?
状态变量
private static volatile boolean backspacePressed = false;
private static volatile boolean ignoreTextChange = false;
TextWatcher
private TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
if(backspacePressed) {
Logger.i("BKSPC");
backspacePressed = false;
if(et.length() <= 1) {
ignoreTextChange = true;
et.setText("b");
et.setSelection(1);
}
return;
}
if(ignoreTextChange) {
ignoreTextChange = false;
return;
}
else {
Logger.i("" + s.charAt(s.length() - 1));
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
};
自定义EditText
public class InterceptTextView extends EditText {
public InterceptTextView(Context context) {
super(context);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent key) {
if(keyCode == KeyEvent.KEYCODE_DEL && key.getAction() == KeyEvent.ACTION_DOWN) {
Logger.i("BCKSPC");
}
return false;
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
outAttrs.actionLabel = null;
outAttrs.inputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
BaseInputConnection connection = new BaseInputConnection(this, false) {
@Override
public boolean deleteSurroundingText (int beforeLength, int afterLength) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
/* In Jelly Bean, they don't send key events for delete.
* Instead, they send beforeLength = 1, afterLength = 0.
* So, we'll just simulate what it used to do. */
if (beforeLength == 0 || beforeLength == 1 && afterLength == 0) {
sendDownUpKeyEventForBackwardCompatibility(KeyEvent.KEYCODE_DEL);
backspacePressed = true;
return true;
}
}
return super.deleteSurroundingText(beforeLength, afterLength);
}
private void sendDownUpKeyEventForBackwardCompatibility (final int code) {
final long eventTime = SystemClock.uptimeMillis();
super.sendKeyEvent(new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, code, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
super.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime, KeyEvent.ACTION_UP, code, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
}
};
return connection;
}
}
我的片段的onCreateView
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
et = new InterceptTextView(getActivity());
et.addTextChangedListener(textWatcher);
ignoreTextChange = true;
et.setText("a");
et.setSelection(1);
return et;
}
解决方法:
这是我的方法.在我的InputConnection中,我将getTextBeforeCursor重写为始终返回“”,以便IME始终认为可以删除至少一个字符.
我还将连接的输入类型设置为InputType.TYPE_NULL,以便传递键事件(来自Google的官方解决方法).
我的自定义EditText:
public class InterceptTextView extends EditText {
public interface OnBackspacePressListener {
public void onBackspacePressed();
}
private OnBackspacePressListener backspaceListener;
public InterceptTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setText(" ");
}
public void setOnBackspacePressListener(OnBackspacePressListener backspaceListener) {
this.backspaceListener = backspaceListener;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_DEL) {
if(backspaceListener != null) {
backspaceListener.onBackspacePressed();
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
outAttrs.actionLabel = null;
outAttrs.inputType = InputType.TYPE_NULL;
BaseInputConnection connection = new BaseInputConnection(this, false) {
@Override
public String getTextBeforeCursor(int ignore, int ignore2) {
return " ";
}
};
return connection;
}
}
我的片段:
public class KeyFragment extends Fragment {
private static volatile boolean backspacePressed = false;
private InterceptTextView et;
private TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
if(backspacePressed) {
backspacePressed = false;
return;
}
else {
Logger.i("" + s.charAt(s.length() - 1));
}
}
@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 View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.keyboard, null);
et = (InterceptTextView) v.findViewById(R.id.keyboard_input_sink);
et.setOnBackspacePressListener(new OnBackspacePressListener() {
@Override
public void onBackspacePressed() {
backspacePressed = true;
Logger.i("BCKSPC");
}
});
et.addTextChangedListener(textWatcher);
return v;
}
}
标签:android-input-method,android-edittext,android-softkeyboard,android 来源: https://codeday.me/bug/20191030/1965069.html