Kon*_*ski 79 android android-recyclerview
如何刷新显示的数据RecyclerView(调用notifyDataSetChanged其适配器)并确保滚动位置重置到它的确切位置?
在好的情况下,ListView所有需要的是检索getChildAt(0),检查它getTop()并setSelectionFromTop在之后使用相同的确切数据进行调用.
在这种情况下似乎不可能RecyclerView.
我想我应该使用它LayoutManager确实提供的scrollToPositionWithOffset(int position, int offset),但是检索位置和偏移的正确方法是什么?
layoutManager.findFirstVisibleItemPosition()和layoutManager.getChildAt(0).getTop()?
或者是否有更优雅的方式来完成工作?
Daw*_*nYu 126
我用这个.^ _ ^
// Save state
private Parcelable recyclerViewState;
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();
// Restore state
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
Run Code Online (Sandbox Code Playgroud)
它更简单,希望它能帮到你!
小智 45
我有类似的问题.我提出了以下解决方案.
使用notifyDataSetChanged是一个坏主意.您应该更具体,然后RecyclerView将为您保存滚动状态.
例如,如果您只需要刷新,或者换句话说,您希望每个视图都被重新绑定,只需执行以下操作:
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
Run Code Online (Sandbox Code Playgroud)
A. *_*gen 20
编辑:要恢复完全相同的明显位置,如同使其看起来完全一样,我们需要做一些不同的事情(请参阅下面的如何恢复确切的scrollY值):
像这样保存位置和偏移:
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);
Run Code Online (Sandbox Code Playgroud)
然后像这样恢复滚动:
LinearLayoutManager manager = (LinearLayoutManager) mRecycler.getLayoutManager();
manager.scrollToPositionWithOffset(mStatePos, (int) mStateOffset);
Run Code Online (Sandbox Code Playgroud)
这将列表恢复到其确切的明显位置.显而易见,因为它看起来与用户相同,但它不会具有相同的scrollY值(因为横向/纵向布局尺寸可能存在差异).
请注意,这仅适用于LinearLayoutManager.
--- 下面如何恢复精确的scrollY,这可能会使列表看起来不同 ---
像这样应用OnScrollListener:
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;
}
};
Run Code Online (Sandbox Code Playgroud)这将在mScrollY中始终存储精确的滚动位置.
将此变量存储在Bundle中,并在状态恢复中将其恢复为另一个变量,我们将其称为mStateScrollY.
在状态恢复之后,在您的RecyclerView重置其所有数据后,重置滚动,使用:
mRecyclerView.scrollBy(0, mStateScrollY);
Run Code Online (Sandbox Code Playgroud)而已.
请注意,将滚动恢复为另一个变量,这很重要,因为将使用.scrollBy()调用OnScrollListener,然后将mScrollY设置为存储在mStateScrollY中的值.如果你不这样做,mScrollY将使滚动值加倍(因为OnScrollListener使用增量,而不是绝对滚动).
国家节约活动可以像这样实现:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(ARGS_SCROLL_Y, mScrollY);
}
Run Code Online (Sandbox Code Playgroud)
并在你的onCreate()中恢复调用它:
if(savedState != null){
mStateScrollY = savedState.getInt(ARGS_SCROLL_Y, 0);
}
Run Code Online (Sandbox Code Playgroud)
片段中的状态保存以类似的方式工作,但实际的状态保存需要一些额外的工作,但是有很多文章处理这个,所以你应该没有问题找出如何,保存scrollY的原则并恢复它保持不变.
Mor*_*ard 12
通过使用 @DawnYu 回答来保持滚动位置,notifyDataSetChanged()如下所示:
val recyclerViewState = recyclerView.layoutManager?.onSaveInstanceState()
adapter.notifyDataSetChanged()
recyclerView.layoutManager?.onRestoreInstanceState(recyclerViewState)
Run Code Online (Sandbox Code Playgroud)
小智 7
是的,你可以通过使适配器构造函数只有一次来解决这个问题,我在这里解释编码部分:
if (appointmentListAdapter == null) {
appointmentListAdapter = new AppointmentListAdapter(AppointmentsActivity.this);
appointmentListAdapter.addAppointmentListData(appointmentList);
appointmentListAdapter.setOnStatusChangeListener(onStatusChangeListener);
appointmentRecyclerView.setAdapter(appointmentListAdapter);
} else {
appointmentListAdapter.addAppointmentListData(appointmentList);
appointmentListAdapter.notifyDataSetChanged();
}
Run Code Online (Sandbox Code Playgroud)
现在您可以看到我已经检查了适配器是否为null,并且仅在它为null时进行初始化.
如果适配器不为null,那么我确信我已经初始化了我的适配器至少一次.
所以我只是将列表添加到适配器并调用notifydatasetchanged.
RecyclerView始终保持滚动的最后位置,因此您不必存储最后位置,只需调用notifydatasetchanged,Recycler视图始终刷新数据而不会返回顶部.
谢谢快乐编码
小智 5
@DawnYu 的最佳答案有效,但 recyclerview 将首先滚动到顶部,然后返回到预期的滚动位置,导致“闪烁状”反应,这是不愉快的。
要刷新recyclerView,尤其是从另一个activity来之后,不闪烁,并且保持滚动位置,需要做如下操作。
希望这可以帮助。
我没有使用过Recyclerview,但是我在ListView上使用过。Recyclerview 中的示例代码:
setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
rowPos = mLayoutManager.findFirstVisibleItemPosition();
Run Code Online (Sandbox Code Playgroud)
它是用户滚动时的监听器。性能开销并不大。这样第一个可见位置就准确了。
| 归档时间: |
|
| 查看次数: |
102525 次 |
| 最近记录: |