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

标签 android android-recyclerview position

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

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

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

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

最佳答案

我自己找到了解决办法:

我扩展了布局管理器:

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

它存储我的目标位置。如果 onLayoutChildren 被 RecyclerView 调用,它会检查适配器 itemCount 是否已经 > 0。如果为真,它会调用 scrollToPositionWithOffset()

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

关于android - 如何告诉 RecyclerView 从特定的项目位置开始,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51499834/

相关文章:

android - 防止 WebView 打开浏览器

java - 多个 XML 文件的 SharedPreferences 管理器类

android - 如何在 retrofit2 android 中解析来自多部分表单数据请求的响应

Android RecyclerView CardView StaggedGridLayoutManager : Independent column scroll

html - 水平绝对居中,负边距,IE6

ios - ImageView 的位置不明确

unity-game-engine - 不使用碰撞器的光线转换

java - 谷歌登录 ApiException : 10:

android - 在 Android Studio 中,notifyDataSetChanged() 不会在 RecyclerView.ViewHolder 中启动 init{ } 吗?

android - 更改适配器数据时 RecyclerView 滚动到顶部位置