美文网首页Android开发经验谈Android技术知识Android开发
AndroidTV——解决EditText焦点无法转移问题

AndroidTV——解决EditText焦点无法转移问题

作者: GitLqr | 来源:发表于2020-03-31 14:05 被阅读0次

    经反馈,在AndroidTV9.0 盒子上发现EditText一旦获取了焦点之后,遥控器上的方向键就无效了,即焦点无法再转移到其他焦点控件上,但这个问题在Android7.0及以下盒子上却不会出现,应该是Android8.0及以上源码做了修改,故查看EditText源码,得知确实是官方源码对方向键进行了处理~

    一、源码分析

    EditText源码中搜索onKeyDown,定位到父类TextView中的onKeyDown()

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        final int which = doKeyDown(keyCode, event, null);
        if (which == KEY_EVENT_NOT_HANDLED) {
            return super.onKeyDown(keyCode, event);
        }
        return true;
    }
    

    很明显doKeyDown()是关键方法,查看该方法的代码逻辑,主意看注释的部分。

    大意:消费掉键盘的箭头事件以防止焦点离开。

    private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent) {
        ...
        if (mMovement != null && mLayout != null) {
            ...
            // Consume arrows from keyboard devices to prevent focus leaving the editor.
            // DPAD/JOY devices (Gamepads, TV remotes) often lack a TAB key so allow those
            // to move focus with arrows.
            if (event.getSource() == InputDevice.SOURCE_KEYBOARD
                    && isDirectionalNavigationKey(keyCode)) {
                return KEY_EVENT_HANDLED;
            }
        }
    
        return mPreventDefaultMovement && !KeyEvent.isModifierKey(keyCode)
                ? KEY_EVENT_HANDLED : KEY_EVENT_NOT_HANDLED;
    }
    
    private boolean isDirectionalNavigationKey(int keyCode) {
        switch(keyCode) {
            case KeyEvent.KEYCODE_DPAD_UP:
            case KeyEvent.KEYCODE_DPAD_DOWN:
            case KeyEvent.KEYCODE_DPAD_LEFT:
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                return true;
        }
        return false;
    }
    

    二、自定义EditText

    通过上面的源码分析,明确原因之后,解决思路也就很明朗了,即:去掉对键盘方向事件的控制即可。但不管是doKeyDown()还是isDirectionalNavigationKey(),这些方法都是私有的,无法通过重写的方式来改变原有逻辑,能重写的只有onKeyDown(),所以,结合FocusFinder通过手动查找焦点控件的方式来处理就好了,完整代码如下:

    /**
     * @author LQR
     * @time 2020/3/31
     * @desc 解决Android8.0 EditText获取焦点后,无法转换焦点问题
     */
    @SuppressLint("AppCompatCustomView")
    public class LQREditText extends EditText {
        public LQREditText(Context context) {
            super(context);
        }
    
        public LQREditText(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public LQREditText(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        public LQREditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (isDirectKeyCode(keyCode)) {
                int direction = FOCUS_DOWN;
                switch (keyCode) {
                    case KeyEvent.KEYCODE_DPAD_UP:
                        direction = FOCUS_UP;
                        break;
                    case KeyEvent.KEYCODE_DPAD_DOWN:
                        direction = FOCUS_DOWN;
                        break;
                    case KeyEvent.KEYCODE_DPAD_DOWN_LEFT:
                        direction = FOCUS_LEFT;
                        break;
                    case KeyEvent.KEYCODE_DPAD_RIGHT:
                        direction = FOCUS_RIGHT;
                        break;
                }
                View nextFocus = FocusFinder.getInstance().findNextFocus((ViewGroup) getParent(), this, direction);
                if (nextFocus != null) {
                    nextFocus.requestFocus();
                    return true;
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    
        private boolean isDirectKeyCode(int keyCode) {
            return keyCode == KeyEvent.KEYCODE_DPAD_UP
                    || keyCode == KeyEvent.KEYCODE_DPAD_DOWN
                    || keyCode == KeyEvent.KEYCODE_DPAD_LEFT
                    || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT;
        }
    }
    
    
    欢迎关注微信公众号:全栈行动

    相关文章

      网友评论

        本文标题:AndroidTV——解决EditText焦点无法转移问题

        本文链接:https://www.haomeiwen.com/subject/nfewuhtx.html