本文介绍了如何告诉RecyclerView从特定位置开始的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望适配器更新后,带有LinearLayoutManager的RecyclerView出现在特定项目的滚动位置. (不是第一个/最后一个位置)表示首先(重新)布局,此给定位置应位于可见区域.它的布局不应在位置0的顶部,然后再滚动到目标位置.

I want my RecyclerView with LinearLayoutManager to show up with scroll position at specific item after adapter got updated. (not first/last position)Means the at first (re-)layout, this given position should be in visible area.It should not layout with position 0 on top and scroll afterwards to target position.

我的适配器以itemCount = 0开头,将其数据加载到线程中,然后通知其实际计数.但是起始位置必须在count仍为0时已经设置好!

My Adapter starts with itemCount=0, loads its data in thread and notifies its real count later. But the start position must be set already while count is still 0!

截至目前,我使用了某种包含scrollToPositionpost Runnable,但这有副作用(从第一个pos开始,立即跳转到目标位置(0->目标),并且似乎不能与DiffUtil(0 ->目标-> 0))

As of now I used some kind of post Runnable containingscrollToPosition but this has side effects (starts at first pos and jumps immediately to target position (0 -> target) and seems not to work well with DiffUtil (0 -> target -> 0))

要澄清:我需要替代layoutManager.setStackFromEnd(true);的东西,例如setStackFrom(position). ScrollToPosition不起作用,如果我在itemCount仍为0时调用它,则它将被忽略.如果我在通知itemCount现在> 0时调用它,它将从0开始布局,并在跳转到目标位置之后短暂跳转.如果我使用DiffUtil.DiffResult.dispatchUpdatesTo(adapter)`,它将完全失败. (从0开始显示,然后滚动到目标位置,然后再次回到位置0)

To clearify: I need alternative to layoutManager.setStackFromEnd(true);, something like setStackFrom(position). ScrollToPosition does not work, if I call it when itemCount is still 0, so it gets ignored. If I call it when I notify that itemCount is now >0, it will layout from 0 and jumps short after to target position. And it fails completely if I use DiffUtil.DiffResult.dispatchUpdatesTo(adapter)`. (shows from 0, then scrolls to target position and then again back to position 0)

推荐答案

我自己找到了一个解决方案:

I found a solution myself:

我扩展了LayoutManager:

I extended the 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;
    }
}

它可以存储目标位置.如果RecyclerView调用了onLayoutChildren,它将检查itemCount是否已经>0.如果为true,则调用scrollToPositionWithOffset().

It stores may target position. If onLayoutChildren is called by RecyclerView, it checks if itemCount is already > 0. If true, it calls scrollToPositionWithOffset().

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

So I can tell immediately what position should be visible, but it will not be told to LayoutManager before position exists in Adapter.

这篇关于如何告诉RecyclerView从特定位置开始的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 19:47