After EditText gets focus, the arrow keys on the remote don’t work. That means you can’t move focus to other focus controls. This doesn’t happen on Android7.0 and below. Android8.0 and above source code is modified, so check EditText source code, know that it is indeed the official source code for the arrow key processing ~

One, source code analysis

Search for onKeyDown in the EditText source and locate onKeyDown() in the parent TextView:

@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;
}
Copy the code

It’s obvious that doKeyDown() is the key method, so look at the code logic for that method and look at the comment section.

Consume arrow events on the keyboard to prevent focus from leaving.

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)) {
			returnKEY_EVENT_HANDLED; }}returnmPreventDefaultMovement && ! 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;
}
Copy the code

Customize EditText

Through the above source code analysis, after clear reasons, the solution is very clear, that is: remove the control of the keyboard direction events. But neither doKeyDown () or isDirectionalNavigationKey (), these methods are private, to change the original logic, through rewriting way can rewrite only onKeyDown (), so, Manually find focus controls with FocusFinder. The complete code is as follows:

/ * * *@author LQR
 * @time 2020/3/31
 * @desc[Fixed] Android8.0 EditText cannot switch focus when getting focus */
@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;
    }
}

Copy the code