RecyclerView焦点滚动

13

我有一个RecyclerView,通常有两列,最多八列。我们经常使用D-PAD导航。当滚动时,我们遇到了一个问题,焦点项目会从左边跳到右边。请参见照片:enter image description here

我注意到,如果接下来的项目已经被缓存,那么在滚动时就没有焦点问题。另一个问题是我的焦点项目可能会出现在粘性标题下面。这是不合适的。因此,我认为如果我让它在滚动时具有某种“阈值”,就会更好。这样,当焦点离屏幕仅剩一个项目时,它将自动滚动。这样,焦点永远不会位于底部或顶部。

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

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));
        }
    }
}

我对如何在滚动时管理焦点的任何想法都持开放态度。

1个回答

12

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

从源代码中可以看出,这个问题是由于GridLayoutManager使用了LinearLayoutManageronFocusSearchFailed()实现所致,该实现在焦点接近RecyclerView的内部边界时被调用。LinearLayoutManager的实现只提供第一个/最后一个元素(取决于滚动方向)。因此,焦点跳到了新行的第一个/最后一个元素。

这个问题的解决方法


1
我做了类似的事情,但是我使用了intercepFocusSearch()。感谢您发布这个错误! - Chad Bingham
对我有用!谢谢! - Crisic
这在2022年仍然是一个问题...不知道你的解决方法是什么?链接已经失效了。 - Trevor
1
@Trevor 奇怪,链接对我有效。 - Vsevolod Ganin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接