提问者:小点点

如何告诉RecyclerView从特定项目位置开始


我希望我的RecyclerView与LinearLayoutManager在适配器更新后显示在特定项目的滚动位置。(不是第一个/最后一个位置)意味着第一次(重新)布局,这个给定的位置应该在可见区域。它不应该在顶部布局位置0,然后滚动到目标位置。

我的适配器从itemCount=0开始,在线程中加载其数据并稍后通知其真实计数。但是必须在计数仍然为0时已经设置了开始位置!

到目前为止,我使用了某种post Runnable包含scrollToPopse,但这有副作用(从第一个pos开始并立即跳转到目标位置(0-

编辑:为了澄清:我需要layoutManager. setStackFromEnd(true)的替代方案;,类似于setStackFrom(位置)。ScrollToPopse不起作用,如果我在itemCount仍然为0时调用它,那么它会被忽略。如果我在通知itemCount现在是时调用它


共3个答案

匿名用户

我自己找到了解决办法:

我扩展了LayoutManager:

  class MyLayoutManager extends LinearLayoutManager {

    private int mPendingTargetPos = -1;
    private int mPendingPosOffset = -1;

    @Override
    public void onLayoutChildren(Recycler recycler, State state) {
        if (mPendingTargetPos != -1 && state.getItemCount() > 0) {
            /*
            Data is present now, we can set the real scroll position
            */
            scrollToPositionWithOffset(mPendingTargetPos, mPendingPosOffset);
            mPendingTargetPos = -1;
            mPendingPosOffset = -1;
        }
        super.onLayoutChildren(recycler, state);
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        /*
        May be needed depending on your implementation.

        Ignore target start position if InstanceState is available (page existed before already, keep position that user scrolled to)
         */
        mPendingTargetPos = -1;
        mPendingPosOffset = -1;
        super.onRestoreInstanceState(state);
    }

    /**
     * Sets a start position that will be used <b>as soon as data is available</b>.
     * May be used if your Adapter starts with itemCount=0 (async data loading) but you need to
     * set the start position already at this time. As soon as itemCount > 0,
     * it will set the scrollPosition, so that given itemPosition is visible.
     * @param position
     * @param offset
     */
    public void setTargetStartPos(int position, int offset) {
        mPendingTargetPos = position;
        mPendingPosOffset = offset;
    }
}

它存储我的目标位置。如果onLayout儿童被RecyclerView调用,它会检查适配器itemCount是否已经

所以我可以立即告诉什么位置应该是可见的,但是在适配器中存在位置之前不会告诉LayoutManager。

匿名用户

你可以试试这个,它会滚动到你想要的位置:

rv.getLayoutManager().scrollToPosition(positionInTheAdapter).

匿名用户

如果您想滚动到特定位置并且该位置是适配器的位置,那么您可以使用StaggeredGridLayoutManagerscrollToPopse

StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
       staggeredGridLayoutManager.scrollToPosition(10);
       recyclerView.setLayoutManager(staggeredGridLayoutManager);

如果我理解这个问题,你想滚动到一个特定的位置,但该位置是适配器的位置,而不是回收器视图的项目位置。

您只能通过LayoutManager来实现这一点。

rv.getLayoutManager().scrollToPosition(youPositionInTheAdapter);