我希望我的带有 LinearLayoutManager 的 RecyclerView 在适配器更新后显示在特定项目的滚动位置。 (不是第一个/最后一个位置) 表示第一个(重新)布局,这个给定的位置应该在可见区域。 它不应在顶部布局位置 0,然后滚动到目标位置。
我的适配器从 itemCount=0 开始,在线程中加载它的数据并稍后通知它的真实计数。但必须在计数仍为 0 时设置起始位置!
截至目前,我使用了某种包含scrollToPosition
的post 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/