Android EditText的焦点无法移动到其他控件及解决方案

最近需要在Android 8.0上开发功能机,碰到一个搜索的时候按方向键没有按键监听的问题。

原因:查询资料发现Android 8.0 EditText的直接父类TextView 中把方向键的监听屏蔽了。不再向下分发,所以我们监听不到方向键。如下

// 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;
}

.....

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

public class EcellEditText extends EditText {

    private static final String TAG = "EcellEditText";

    public EcellEditText(Context context) {
        super(context);
    }

    public EcellEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EcellEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_DPAD_UP || keyCode == KeyEvent.KEYCODE_DPAD_DOWN ||
                keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ||
                keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
            int direction = 0;
            switch (keyCode) {
                case KeyEvent.KEYCODE_DPAD_UP:
                    if (getCurrentCursorLine() == 0) {
                        direction = FOCUS_UP;
                    }
                    break;
                case KeyEvent.KEYCODE_DPAD_DOWN:
                    if (getCurrentCursorLine()  + 1 == getLineCount()) {
                        direction = FOCUS_DOWN;
                    }
                    break;
                case KeyEvent.KEYCODE_DPAD_LEFT:
                    if (getSelectionStart() == 0) {
                        direction = FOCUS_LEFT;
                    }
                    break;
                case KeyEvent.KEYCODE_DPAD_RIGHT:
                    if (getSelectionStart() == getText().length()) {
                        direction = FOCUS_RIGHT;
                    }
                    break;
            }
            View nextFocus = null;
            int count = 0;
            // 此处的10可以自由调整,根据控件嵌套层数调整。
            while (nextFocus == null && direction != 0 && count < 10) {
                ViewParent viewParent = getViewParent(count, getParent());
                if (null != viewParent && viewParent instanceof ViewGroup) {
                    nextFocus = FocusFinder.getInstance().findNextFocus(((ViewGroup) viewParent), this, direction);
                }
                count++;
            }
            if (nextFocus != null) {
                nextFocus.requestFocus();
                return true;
            } else {
                if (null != mKeyCodeListener) {
                    mKeyCodeListener.onKeyCode(keyCode);
                }
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        int keyCode = event.getKeyCode();
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0 &&
                event.getAction() == KeyEvent.ACTION_UP && getText().length() > 0) {
            dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
        }
        return super.dispatchKeyEvent(event);
    }

    private ViewParent getViewParent(int count, ViewParent view) {
        if (count <= 0 || view == null) {
            if (view == null) {
                return null;
            }
            return view.getParent();
        }
        count--;
        return getViewParent(count, view.getParent());
    }

    private int getCurrentCursorLine() {
        int selectionStart = Selection.getSelectionStart(getText());
        return selectionStart == -1 ? -1 : getLayout().getLineForOffset(selectionStart);
    }

    private KeyCodeListener mKeyCodeListener;

    public void setKeyCodeListener(KeyCodeListener keyCodeListener) {
        this.mKeyCodeListener = keyCodeListener;
    }

    public interface KeyCodeListener {

        void onKeyCode(int keyCode);

    }
}

如此一来我们就可以监听到键盘方向键,愉快的完成开发工作

感谢 GitLqr 分享

你可能感兴趣的:(原创,android)