RecyclerView focus scrolling

偶尔善良 提交于 2019-12-17 19:24:59

问题


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.


回答1:


I reported this bug to AOSP issue tracker: issue 190526

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.

My workaround for this issue.



来源:https://stackoverflow.com/questions/31596801/recyclerview-focus-scrolling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!