关于按键回车改变焦点为其他编辑框引发bug解决探索

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (BaseUtil.isEnterKey(actionId, event)) {
                    onMaterialEnter(v.getText().toString());
                }
                return true;
            }

在按键回车同样触发onEditorAction 返回true 然后发现其他编辑框为空,让他调用其他编辑框焦点,结果会立马调回来,哪怕post()但是软键盘没有此问题。。

因此此种情况怕是要多延长几秒了。目前没想到解决办法。
2022-11-21 14:54:07
终于找到了解决办法,并且代码进行了进一步的封装,还可以防止快速点击,当按键回车返回了true,那么在onEditorActionListenre将不会触发,
另外如果onKey返回false,那么 onEditorAction分别会受到,按下,和抬起的按键事件。

/**
     * Return true if you have consumed the action, else false.
     *
     * @param actionId
     * @param event
     * @return
     */
    public static boolean isKeyEnter(int actionId, KeyEvent event) {
        boolean result = actionId == EditorInfo.IME_ACTION_DONE ||
                actionId == EditorInfo.IME_ACTION_NEXT ||
                actionId == EditorInfo.IME_ACTION_GO ||
                actionId == EditorInfo.IME_ACTION_SEARCH ||
                actionId == EditorInfo.IME_ACTION_SEND ||
                (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER
                        && event.getAction() == KeyEvent.ACTION_UP);

        return result;
    }



    /**
     * 1 回车抬起触发 0 回车按下触发, 其他 代表返回false,交给系统处理
     *
     * @param keyCode
     * @param event
     * @return
     */
    public static int isHardKeyEnter(int keyCode, KeyEvent event) {
        boolean result =
                (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER
                        && event.getAction() == KeyEvent.ACTION_UP);
        if (result) {
            return 1;

        } else if (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER
                && event.getAction() == KeyEvent.ACTION_DOWN) {
            return 0;//自己处理消费
        }
        return -1;
    }
    public static void setOnEditorActionEnterAndScanListener(Activity activity, EditText editText, DialogUtils.INotify<EditText> iNotify) {
        editText.setOnKeyListener((v, keyCode, event) -> {
            int result = BaseUtil.isHardKeyEnter(keyCode, event);
            if (result == 1) {//按键回车抬起
                AppUtils.closeKeyboard(activity);
                iNotify.onNotify(editText);
                return true;
            } else if (result == 0) {//按键回车按下
                return true;

            }
            return false;
        });

        editText.setOnEditorActionListener((v, actionId, event) -> {
            if (BaseUtil.isKeyEnter(actionId, event)) {
                if (ButtonUtils.isFastDoubleClick(actionId)) {
                    return true;
                }
                AppUtils.closeKeyboard(activity);
                iNotify.onNotify(editText);
            }
            return true;
        });
    }

但是又发现了一个问题,
假设第一个编辑框没重写设置,而第二个编辑框设置了,从第一个编辑框按键回车会自动触发第二个编辑框的onKeyEvent从而发起了逻辑,依然是有问题的,要从源头上禁止按键回车改变光标 才能彻底解决问题,
虽然无法调试源码但是根据自定义view重写获取焦点追踪到了调用的代码处,为textview的onKeyUp事件所触发。

if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0
                            || shouldAdvanceFocusOnEnter()) {

  if (!hasOnClickListeners()) {
                            View v = focusSearch(FOCUS_DOWN);
                            if (v != null) {
                                if (!v.requestFocus(FOCUS_DOWN)) {
                                    throw new IllegalStateException("focus search returned a view "
                                            + "that wasn't able to take focus!");
                                }

                                super.onKeyUp(keyCode, event);
                                return true;
                            } else if ((event.getFlags()
                                    & KeyEvent.FLAG_EDITOR_ACTION) != 0) {

                                InputMethodManager imm = getInputMethodManager();
                                if (imm != null && imm.isActive(this)) {
                                    imm.hideSoftInputFromWindow(getWindowToken(), 0);
                                }
                            }
                        }




}

另外也要满足inputtype =TYPE_CLASS_TEXT之类

private boolean shouldAdvanceFocusOnEnter() {
        if (getKeyListener() == null) {
            return false;
        }

        if (mSingleLine) {
            return true;
        }

        if (mEditor != null
                && (mEditor.mInputType & EditorInfo.TYPE_MASK_CLASS)
                        == EditorInfo.TYPE_CLASS_TEXT) {
            int variation = mEditor.mInputType & EditorInfo.TYPE_MASK_VARIATION;
            if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
                    || variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT) {
                return true;
            }
        }

        return false;
    }

2022-11-26 12:28:00
经过源码分析在onEdiAction里面 无论是down还是up全部返回true,这样就不会交给系统处理焦点了,
而响应逻辑就处理按下就好了。
第二个编辑框设置setOnEditActionListenlier然后立马写了尝试发起调用第一个编辑框的获取焦点,结果是 又跳回来了,
如果第一个编辑框没设置焦点相关事件,第二个 触发 第一个, 第一个又调用了 第二个的焦点,也就是第一个的onKeyUp触发,然后执行如下代码

if (!hasOnClickListeners()) {
                            View v = focusSearch(FOCUS_DOWN);

                            if (v != null) {
                                if (!v.requestFocus(FOCUS_DOWN)) {

又让第二个获取了焦点。
去掉input=text 或者非单行,则正常运行,因此目前处理起来有点棘手。

if (mSingleLine) {
            return true;
        }

        if (mEditor != null
                && (mEditor.mInputType & EditorInfo.TYPE_MASK_CLASS)
                        == EditorInfo.TYPE_CLASS_TEXT) {
            int variation = mEditor.mInputType & EditorInfo.TYPE_MASK_VARIATION;
            if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
                    || variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT) {
                return true;
            }
        }

满足此条件

if (mEditor != null && mEditor.mInputContentType != null
                            && mEditor.mInputContentType.onEditorActionListener != null
                            && mEditor.mInputContentType.enterDown) {
                        mEditor.mInputContentType.enterDown = false;
                        if (mEditor.mInputContentType.onEditorActionListener.onEditorAction(
                                this, EditorInfo.IME_NULL, event)) {
                            return true;
                        }
                    }

目前第一个编辑框&& mEditor.mInputContentType !=是空的。所以走了shouldAdvanceFocusOnEnter

最后总结,方法是有了,但是要改的地方太多不太现实。。
比如

public boolean onKeyUp(int keyCode, KeyEvent event) {
        if(keyCode==KeyEvent.KEYCODE_ENTER){
            return true;
        }

这导致硬件回车无法触发光标下移事件

最后的调整版本 就是按键回车这种不应该立马回调,让事件流失掉,就不会连环触发另外一个的按键抬起事件了。

public static void setOnEditorActionEnterAndScanListener(Activity activity, EditText editText, DialogUtils.INotify<EditText> iNotify) {

        editText.setOnKeyListener((v, keyCode, event) -> {
            int result = BaseUtil.isHardKeyEnter(keyCode, event);
            if (result == 1) {//按键回车抬起
                if (BuildConfig.DEBUG) {
                    Log.w("Event", "down" + event.getDownTime() + event.getEventTime() + "," + event.getEventTime() + ",fucus:" + editText.hasFocus());

                }
                AppUtils.closeKeyboard(activity);
                if (ButtonUtils.isFastDoubleClick(keyCode)) {
                    return true;
                }
                if (TextUtils.isEmpty(editText.getText().toString())) {
                    return true;
                }
//                return false;
                //让事件延迟流失掉,这样再请求另外的焦点应该不会连锁反应了。
                editText.postDelayed(new Runnable() {
                    @Override
                    public void run() {

                        iNotify.onNotify(editText);
                    }
                }, 10);
                return true;

            } else if (result == 0) {//按键回车按下
                return true;

            }
            return false;
        });


        editText.setOnEditorActionListener((v, actionId, event) -> {
            if (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
                return true;
            }
            if (BaseUtil.isKeyEnterOrHardKeyPress(actionId, event)) {
                AppUtils.closeKeyboard(activity);
                if (ButtonUtils.isFastDoubleClick(actionId)) {
                    return true;
                }
                iNotify.onNotify(editText);
            }
            return true;
        });
    }

但是问题依然没解决,

2022-11-26 13:24:13

把抬起改成按下,就可以确保按下的时候百分百是当前的。
这次终于解决了,下班

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值