向RecyclerView添加适当的键盘支持 [英] Adding proper keyboard support to 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 View
s.
是否有任何变通办法或更好的做法来正确处理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屋!