RecyclerView 焦点滚动 [英] RecyclerView focus scrolling

查看:38
本文介绍了RecyclerView 焦点滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 RecyclerView,通常有两列,最多八列.我们使用了很多 D-PAD 导航.我们在滚动时遇到问题,焦点项目会从左跳到右.看照片:

I have a RecyclerView with usually two columns and up to eight. We use a lot of D-PAD navigation. We have a problem when scrolling, the focused item will jump from left to right. See photos:

我注意到如果接下来出现的项目被缓存,滚动时没有焦点问题.我的另一个问题是我的焦点项目可能出现在我的粘性标题下方.这是不希望的.所以我觉得如果我这样做了,滚动时它会有一种阈值".这样当焦点在屏幕外的一项内时,它会滚动.这样,焦点永远不会在最底部或最顶部.

I noticed that if the items that are coming up next are cached, there is no focus problem when scrolling. Another problem I have is my focus item can appear below my sticky header. This is not desired. So I feel like if I made it so when scrolling it would have a sort of "threshold". This way when the focus is within one item of being off screen, it will scroll. This way the focus is never at the very bottom, or the very top.

考虑到这一点,我尝试了这种方法但没有运气:

With that in mind, I tried this approach with no luck:

RecyclerView rv;

@Override
public void onFocusChange(View v, boolean hasFocus) {
    if(!v.hasFocus()) {
        Log.w(TAG, "View v did not have focus");
        return;
    }

    final int index = rv.getChildPosition(v); //adapter pos
    if(index == NO_POSITION) {
        Log.w(TAG, "Recycler view did not have view");
        return;
    }

    int position = rv.indexOfChild(v);  // layout pos
    int lastPos = rv.getChildCount();   // layout pos
    int span = getLayoutManager().getSpanCount();
    int threshold = 2 * span;
    Log.d(TAG, String.format("Position: %1$d. lastPos: %2$d. span: %3$d. threshold: %4$d", position, lastPos, span, threshold));

    if (position >= (lastPos - threshold)) {
        //scroll down if possible
        int bottomIndex = rv.getChildPosition(rv.getChildAt(lastPos));
        if (bottomIndex < getItemCount()) {
            //scroll down
            int scrollBy = v.getHeight();
            recycler.scrollBy(0, scrollBy);
            Log.d(TAG, String.format("Scrolling down by %d", scrollBy));

        }

    } else if (position <= threshold) {
        //scroll up if possible
        int topIndex = rv.getChildPosition(rv.getChildAt(0));
        if (topIndex > 0) {
            //scroll up
            int scrollBy = v.getHeight();
            recycler.scrollBy(0, -scrollBy);
            Log.d(TAG, String.format("Scrolling up by %d", -scrollBy));
        }
    }
}

我愿意接受有关如何在滚动时管理焦点的任何想法.

I am open to any ideas on how to manage the focus when scrolling.

推荐答案

我向 AOSP 问题跟踪器报告了这个错误:issue 190526

I reported this bug to AOSP issue tracker: issue 190526

正如我从源代码中看到的,问题是因为 GridLayoutManager 使用 LinearLayoutManageronFocusSearchFailed() 实现,它在焦点接近时调用RecyclerView 的内边框.LinearLayoutManager 的实现只提供第一个/最后一个(取决于滚动方向)元素.因此焦点跳转到新行的第一个/最后一个元素.

As I can see from source the issue is because GridLayoutManager uses LinearLayoutManager's implementation of onFocusSearchFailed() which is called when focus approaches the inner border of RecyclerView. LinearLayoutManager's implementation just offers first/last (depends on scrolling direction) element. Hence focus jumps to first/last element of new row.

我对此问题的解决方法.

这篇关于RecyclerView 焦点滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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