导航到列表末尾时如何保持RecyclerView的最后一项焦点?

Xia*_*zou 6 android android-tv android-recyclerview

我在电视开发中使用了带有HORIZONTAL方向的RecyclerView,它由D-pad控制,从左到右导航列表.当导航到最右边的列表时,RecyclerView的最后一项始终失去焦点.

那么当导航到列表末尾时,如何保持最后一项的焦点?

Xia*_*zou 11

我挖掘了RecyclerView的源代码,在LayoutManager中找到了onInterceptFocusSearch方法,也就是RecyclerView的内部类.

/**
 * This method gives a LayoutManager an opportunity to intercept the initial focus search
 * before the default behavior of {@link FocusFinder} is used. If this method returns
 * null FocusFinder will attempt to find a focusable child view. If it fails
 * then {@link #onFocusSearchFailed(View, int, RecyclerView.Recycler, RecyclerView.State)}
 * will be called to give the LayoutManager an opportunity to add new views for items
 * that did not have attached views representing them. The LayoutManager should not add
 * or remove views from this method.
 *
 * @param focused The currently focused view
 * @param direction One of { @link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
 *                  {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT},
 *                  {@link View#FOCUS_BACKWARD}, {@link View#FOCUS_FORWARD}
 * @return A descendant view to focus or null to fall back to default behavior.
 *         The default implementation returns null.
 */
public View onInterceptFocusSearch(View focused, int direction) {
    return null ;
}
Run Code Online (Sandbox Code Playgroud)

这使得LayoutManager有机会在使用FocusFinder的默认行为之前拦截初始焦点搜索.

所以我覆盖了下面的onInterceptFocusSearch,并将CustomGridLayoutManager用于我的RecylerView,它的工作方式非常迷人.

public class CustomGridLayoutManager extends android.support.v7.widget.GridLayoutManager {

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

        public CustomGridLayoutManager(Context context, int spanCount) {
            super (context, spanCount);
        }

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

        @Override
        public View onInterceptFocusSearch(View focused, int direction) {
            int pos = getPosition(focused);
            int count = getItemCount();
            int orientation = getOrientation();


            **********
            do some logic
            what i did was return the focused View when the focused view is the last item of RecyclerView.
            **********

            return super .onInterceptFocusSearch(focused, direction);
        }
}
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢你!这是一个很好的解决方案.让我添加代码:`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; } (5认同)