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 分享

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以在RecyclerView的Adapter中为每个EditText设置FocusChange监听器,然后在监听器中处理焦点变化的逻辑。例如,当EditText失去焦点时,可以调用其clearFocus()方法来让其失去焦点。同时,你需要在RecyclerView的Item布局中添加一个可获取焦点控件,例如一个Button,当用户点击这个Button时,你可以调用RecyclerView的requestFocus()方法来让RecyclerView获取焦点,这样所有的EditText就会失去焦点了。 以下是一个简单的示例代码: ```java public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { private List<String> mData; public MyAdapter(List<String> data) { mData = data; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { holder.mEditText.setText(mData.get(position)); holder.mEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { holder.mEditText.clearFocus(); } } }); holder.mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { holder.itemView.requestFocus(); } }); } @Override public int getItemCount() { return mData.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { public EditText mEditText; public Button mButton; public ViewHolder(@NonNull View itemView) { super(itemView); mEditText = itemView.findViewById(R.id.edit_text); mButton = itemView.findViewById(R.id.button); } } } ``` 在上述代码中,我们为每个EditText设置了FocusChange监听器,并在监听器中处理了焦点变化的逻辑。同时,在Item布局中添加了一个Button,并为其设置了点击事件,当用户点击这个Button时,我们调用RecyclerView的requestFocus()方法来让RecyclerView获取焦点,从而让所有的EditText失去焦点

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值