Android TV中多个RecyclerView焦点问题

在图1中存在三个名称依次为Top、Center、Bottom的RecyclerView
图1

碰到如下几个问题:

  1. 在top中按遥控器左右快速移动时,焦点会飞到其他的RecyclerView中;(center和bottom也是类似的) 想要的效果:在top、center、bottom中左右移动焦点时,只能在当前RecyclerView中移动,除非是按上下键才能移动到其他的RecyclerView

  2. 当前焦点在Item0的时候,再向左移动直接移动到RecyclerView的最后一个Item19上;而在Item的19上时,再向右移动直接移动到Item0上。

这两个问题目前还没有找到好的解决办法,如果能给一些指点或者思路,不胜感激!



示例代码Github地址

现在勉勉强强将第一个需求解决了,但是当RecyclerView中的Item布局复杂并且数据很多的时候快速滑动光标还是会飞,没有完美解决!

阅读 19.7k
4 个回答
新手上路,请多包涵

http://stackoverflow.com/ques...
*长按向下向右,view滚动速度跟不上key焦点转移速度, 这个时候焦点view会被置为null,然后屏幕上第一个能获得焦点的view获得焦点. 这个链接的解决方法是加上key的间隔限制*.
private long mLastKeyDownTime = 0;

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    long current = System.currentTimeMillis();
    boolean res;
    if (current - mLastKeyDownTime < 150) {
        res = true;
    } else {
        res = super.onKeyDown(keyCode, event);
        mLastKeyDownTime = current;
    }
    return res;
}
新手上路,请多包涵

layoutManager onFocusSearchFailed()

覆写LinearLayoutManager 下的onInterceptFocusSearch可以解决需求2

public class FocusFixedLinearLayoutManager extends android.support.v7.widget.LinearLayoutManager {


    public FocusFixedLinearLayoutManager(Context context) {
        super (context);
    }
    public FocusFixedLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context,orientation,reverseLayout);
    }

    public FocusFixedLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr,
                                         int defStyleRes) {
        super(context,attrs,defStyleAttr,defStyleRes);
    }

    @Override
    public View onInterceptFocusSearch(View focused, int direction) {

        int pos = getPosition(focused);
        int count = getItemCount();
        int orientation = getOrientation();
        if (direction == View.FOCUS_RIGHT) {
            View view = getChildAt(getChildCount() - 1);
            if (view == focused){
                return focused;}
        } else if (direction == View.FOCUS_LEFT) {
            View view = getChildAt(0);
            if (view == focused) {
                return focused;
            }
        }
            return super .onInterceptFocusSearch(focused, direction);
    }
}

你的问题是:左右快速移动,焦点会跑到其它 RecyclerView 上.
其实这个问题,Leanback就已经解决了的.
VerticalGridView

leaback 简单的 Demo 数据.

final ArrayObjectAdapter rowsAdapter = new ArrayObjectAdapter(new TestPresenterSelector());  
ItemBridgeAdapter itemBridgeAdapter = new ItemBridgeAdapter(rowsAdapter);  
hGridView.setAdapter(itemBridgeAdapter);  
//  
for (int i = 0; i < 30; i++) {  
   ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new AppItemPresenter(i));  
  List<String> itemList = new ArrayList<>();  
 for (int j = 0; j < 30; j++) {  
       itemList.add("item" \+ j);  
  }  
   listRowAdapter.addAll(0, itemList);  
  HeaderItem settingHeader = new HeaderItem(i, "测试" \+ i);  
  ListRow listRow = new ListRow(i, settingHeader, listRowAdapter);  
  rowsAdapter.add(listRow);  
  // rowsAdapter.add("item" + i);  
}  
//  
itemBridgeAdapter.notifyDataSetChanged();

image.png

到达右边的底部的时候,长按右键,焦点是不会下去的.

如何设置:

  1. 设置这个属性 setFocusOutAllowed(false, false) 左右的.
  2. 如果你不想 Item一直保持在中间,可以设置setFocusScrollStrategy 这个属性(FOCUS_SCROLL_ALIGNED, FOCUS_SCROLL_ITEM等).

为何?因为 Leanback 的 GridLayoutManager 的 onInterceptFocusSearch 进行了处理.

也处理了 放大遮挡问题,焦点搜索失败的问题 onFocusSearchFailed,也处理了焦点记忆问题 onAddFocusables.

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题