向RecyclerView添加适当的键盘支持 [英] Adding proper keyboard support to RecyclerView

查看:234
本文介绍了向RecyclerView添加适当的键盘支持的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我以前的问题之一中,我问了一下(并在下面回答了自己的问题博客文章)如何正确处理键盘上的按键输入RecyclerView.

In one of my previous questions, I asked (and answered by myself following this blog post) how to properly handle key input on a RecyclerView.

现在,我意识到如果按住箭头键(例如向下键),则向下滚动停止,并且RecyclerView失去焦点,可能是因为滚动速度比所有子代View的生成速度都要快

Now I realized that if I keep an arrow key pressed, let's say down key, the scrolling downwards stops and the RecyclerView loses its focus, probably because the scrolling is faster than the generation of all the children Views.

是否有任何变通办法或更好的做法来正确处理RecyclerView上的硬件键盘输入?

Is there any workaround or better practice to properly handle hardware keyboard inputs on a RecyclerView?

更新:

我在此处发布了一个基本示例,现在它可以正常工作,不再有焦点损失.

I published a basic example here, it works flawlessly now, no more focus losses.

推荐答案

我设法实现了一个抽象的Adapter类,该类能够跟踪所选项目而不会丢失项目焦点,可以找到一个示例项目

I managed to implement an abstract Adapter class capable of keeping track of the selected item without losing item focus, a sample project can be found here, the specific implementation of the adapter class is below:

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.KeyEvent;
import android.view.View;


/**
 * Created by vektor on 31/05/16.
 */
public abstract class InputTrackingRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH>{

    private Context mContext;
    private int mSelectedItem = 0;
    private RecyclerView mRecyclerView;

    public InputTrackingRecyclerViewAdapter(Context context){
        mContext = context;
    }

    @Override
    public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);

        mRecyclerView = recyclerView;
        // Handle key up and key down and attempt to move selection
        recyclerView.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();

                // Return false if scrolled to the bounds and allow focus to move off the list
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (isConfirmButton(event)) {
                        if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) == KeyEvent.FLAG_LONG_PRESS) {
                            mRecyclerView.findViewHolderForAdapterPosition(mSelectedItem).itemView.performLongClick();
                        } else {
                            event.startTracking();
                        }
                        return true;
                    }
                    else {
                        if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                            return tryMoveSelection(lm, 1);
                        } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                            return tryMoveSelection(lm, -1);
                        }
                    }
                }
                else if(event.getAction() == KeyEvent.ACTION_UP && isConfirmButton(event)
                        && ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != KeyEvent.FLAG_LONG_PRESS)){
                    mRecyclerView.findViewHolderForAdapterPosition(mSelectedItem).itemView.performClick();
                    return true;
                }
                return false;
            }
        });
    }

    private boolean tryMoveSelection(RecyclerView.LayoutManager lm, int direction) {
        int nextSelectItem = mSelectedItem + direction;

        // If still within valid bounds, move the selection, notify to redraw, and scroll
        if (nextSelectItem >= 0 && nextSelectItem < getItemCount()) {
            notifyItemChanged(mSelectedItem);
            mSelectedItem = nextSelectItem;
            notifyItemChanged(mSelectedItem);
            //lm.scrollToPosition(mSelectedItem);
            mRecyclerView.smoothScrollToPosition(mSelectedItem);
            return true;
        }

        return false;
    }

    public Context getContext(){ return mContext; }

    public int getSelectedItem() { return mSelectedItem; }
    public void setSelectedItem(int selectedItem) { mSelectedItem = selectedItem; }

    public RecyclerView getRecyclerView() { return mRecyclerView; }


    @Override
    public void onBindViewHolder(VH holder, int position) {
        onBindViewHolder(holder, position);
    }

    public static boolean isConfirmButton(KeyEvent event){
        switch (event.getKeyCode()){
            case KeyEvent.KEYCODE_ENTER:
            case KeyEvent.KEYCODE_DPAD_CENTER:
            case KeyEvent.KEYCODE_BUTTON_A:
                return true;
            default:
                return false;
        }
    }


}

这篇关于向RecyclerView添加适当的键盘支持的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆