编程语言
首页 > 编程语言> > 我自己的应用程序中的Android拦截软按键-Backspace问题

我自己的应用程序中的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