Android TV中多个RecyclerView焦点问题

发布于 2022-09-04 05:06:58 字数 742 浏览 17 评论 0

在图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布局复杂并且数据很多的时候快速滑动光标还是会飞,没有完美解决!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

巴黎夜雨 2022-09-11 05:07:06

你的问题是:左右快速移动,焦点会跑到其它 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.

岁月静好 2022-09-11 05:07:05

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()

纸伞微斜 2022-09-11 05:07:05

覆写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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文