最近需要在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);
}
}
如此一来我们就可以监听到键盘方向键,愉快的完成开发工作