当前位置: 首页 > 知识库问答 >
问题:

刷新RecyclerView中的数据并保持其滚动位置

施晗日
2023-03-14

如何刷新显示在RecycraView中的数据(在其适配器上调用通知数据设置更改),并确保滚动位置被重置到它原来的位置?

如果是良好的ol'ListView则只需检索getChildAt(0),检查其getTop(),然后使用相同的精确数据调用setSelectionFromTop

RecyclerView的情况下,这似乎是不可能的。

我想我应该使用它的LayoutManager,它确实提供了scrollToPositionRetOffset(int位置,int偏移量),但是检索位置和偏移量的正确方法是什么?

layoutManager。findFirstVisibleItemPosition()布局管理器。getChildAt(0)。getTop()

还是有更优雅的方法来完成这项工作?

共有3个答案

伍溪叠
2023-03-14

编辑:要恢复完全相同的外观位置,如中所示,使其看起来完全一样,我们需要做一些不同的事情(请参见下面如何恢复精确的滚动值):

像这样保存位置和偏移:

LinearLayoutManager manager = (LinearLayoutManager) mRecycler.getLayoutManager();
int firstItem = manager.findFirstVisibleItemPosition();
View firstItemView = manager.findViewByPosition(firstItem);
float topOffset = firstItemView.getTop();

outState.putInt(ARGS_SCROLL_POS, firstItem);
outState.putFloat(ARGS_SCROLL_OFFSET, topOffset);

然后像这样还原卷轴:

LinearLayoutManager manager = (LinearLayoutManager) mRecycler.getLayoutManager();
manager.scrollToPositionWithOffset(mStatePos, (int) mStateOffset);

这会将列表恢复到其确切的外观位置。显而易见,因为它在用户看来是相同的,但它不会有相同的滚动值(因为横向/纵向布局尺寸可能不同)。

请注意,这仅适用于LinearLayoutManager。

下面是如何恢复精确的scrollY,这可能会使列表看起来不同---

>

private int mScrollY;
private RecyclerView.OnScrollListener mTotalScrollListener = new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        mScrollY += dy;
    }
};

这将始终在mScrollY中存储确切的滚动位置。

将这个变量存储在Bundle中,并在状态恢复时将其恢复到另一个变量,我们称之为mStateScrollY。

状态恢复后,在RecycraView重置了所有数据后,用以下方式重置滚动:

mRecyclerView.scrollBy(0, mStateScrollY);

就这样。

请注意,您将滚动还原为不同的变量,这很重要,因为OnScrollListener将被. scrollBy()调用,随后将把mScrollY设置为存储在mStateScrollY中的值。如果不这样做,mScrollY将具有两倍的滚动值(因为OnScrollListener使用增量,而不是绝对滚动)。

活动中的状态节省可以通过以下方式实现:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(ARGS_SCROLL_Y, mScrollY);
}

要恢复,请在onCreate()中调用

if(savedState != null){
    mStateScrollY = savedState.getInt(ARGS_SCROLL_Y, 0);
}

片段中的状态保存的工作方式类似,但实际的状态保存需要一些额外的工作,但是有很多文章都在讨论这一点,所以您应该可以找到保存滚动条和恢复滚动条的原理保持不变的方法。

公冶昆杰
2023-03-14

我也有类似的问题。我提出了以下解决方案。

使用notifyDataSetChanged是个坏主意。你应该更具体一些,然后RecyclerView会为你保存滚动状态。

例如,如果您只需要刷新,或者换句话说,您希望每个视图都重新索引,只需执行以下操作:

adapter.notifyItemRangeChanged(0, adapter.getItemCount());
钮鸿煊
2023-03-14

我用这个。^_^

// Save state
private Parcelable recyclerViewState;
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();

// Restore state
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);

它更简单,希望它能帮助你!

 类似资料:
  • 问题内容: 有人可以告诉我我在做什么错吗?我需要在一段时间后刷新页面,但是它会刷新到页面顶部,我需要不更改页面位置!所以这是我现在无法使用的,是meta标签吗?这是我所没有的仍然不刷新必须做错了什么吗? 这是我本来的… 阅读了一些初始答案后,我将其更改为… 问题答案: 更新 您可以使用下面提到的方法代替下面的强制技巧。 将HTML替换为:

  • 问题内容: 我的问题是当我在回收视图中滚动数据时,所以加载了新数据,但问题是当新数据加载时,回收视图从第一个产品开始, 我需要保持旧的位置,只滚动新数据,而不滚动所有旧数据 目前,我正在添加文件adeptoer文件和主文件的完整代码, 问题答案: 试试这个:

  • 我正在尝试用recyclerview做一个布局,比如视频。我做了一个recyclerview,它会在一定时间间隔后更新列表,但问题是在数据更新后,它会自动滚动到顶部位置。我想做一些像视频的东西。https://youtu.be/omcS-6LeKoo当将适配器数据RecyclerView notifyDataSetChanged scrolls更改为top position时,我尝试使用从SO R

  • 问题内容: 我正在MVC中从事一个项目,并且对此有所了解。有一些成长的烦恼,但一旦您找出来,那还不错。在WebForms世界中,真正简单的一件事是保持页面上的滚动位置。您所要做的只是将MaintenanceScrollPositionOnPostback属性设置为true。但是,在MVC中,我不使用回发,因此这对我不起作用。处理此问题的标准方法是什么? 编辑: Ajax是可以接受的,但我也想知道如

  • 我有一个非常标准的,带有垂直。我一直在顶部插入新项目,并调用 < 我希望列表保持滚动到顶部;总是显示第0个位置。 从我的需求的角度来看,< code>LayoutManager根据项目的数量表现不同。 虽然所有项目都适合屏幕,但它的外观和行为与我预期的一样:新项目总是出现在顶部,并移动其下的所有项目。 但是,一旦项目数超过RecyclerView的界限,新项目就会添加到当前可见项目的上方,但可见项

  • 问题内容: 我的下拉列表中有很多复选框,因此此容器具有滚动功能。但是,当我单击任何复选框时,它会自行选择\取消选择,然后更改状态。 因此,问题在于重新渲染后,此容器又回到了顶部。是否可以在渲染后保持容器的滚动而不将其保存到状态? 问题答案: 您可以在提交阶段之前保存滚动位置的“快照”。 getSnapshotBeforeUpdate()显示您正在寻找的种类。 该文档示例将当前滚动位置保存在生命周期