android - 如何告诉 RecyclerView 从特定项目位置开始
问题描述
我希望我的带有 LinearLayoutManager 的 RecyclerView 在适配器更新后显示特定项目的滚动位置。(不是第一个/最后一个位置)表示第一个(重新)布局,这个给定的位置应该在可见区域。它不应该在顶部放置位置 0,然后滚动到目标位置。
我的适配器从 itemCount=0 开始,在线程中加载其数据并稍后通知其实际计数。但是必须在 count 仍然为 0 时设置起始位置!
截至目前,我使用了某种post Runnable
包含scrollToPosition
,但这有副作用(从第一个 pos 开始并立即跳转到目标位置(0 -> 目标),并且似乎不适用于 DiffUtil(0 -> 目标 -> 0))
编辑:清除:我需要替代layoutManager.setStackFromEnd(true);
,例如setStackFrom(position)
. ScrollToPosition 不起作用,如果我在 itemCount 仍然为 0 时调用它,那么它会被忽略。如果我在通知 itemCount 现在 > 0 时调用它,它将从 0 开始布局并在目标位置之后快速跳转。如果我使用 DiffUtil.DiffResult.dispatchUpdatesTo(adapter)`,它会完全失败。(从 0 开始显示,然后滚动到目标位置,然后再次回到位置 0)
解决方案
我自己找到了解决方案:
我扩展了 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;
}
}
它存储我的目标位置。如果onLayoutChildren
被 RecyclerView 调用,它会检查适配器 itemCount 是否已经 > 0。如果为 true,它会调用scrollToPositionWithOffset()
.
所以我可以立即知道哪个位置应该是可见的,但在位置存在于适配器之前不会告诉 LayoutManager。
推荐阅读
- c# - 我可以在我的代码中使用我的标头上发送的 JWT 令牌吗?
- html - 图标未正确加载
- c# - 每次光标在它上面时,我如何统一创建我的游戏对象的亮点?
- azure-resource-manager - ARM模板中是否可以有条件属性
- r - 如何使用 rmarkdown::render() 在 html 中呈现 gganimate 图,而不产生不需要的输出
- php - 如何将 REQUEST_URI 从 htaccess 传递给 PHP
- xml - alpakka-xml 可以处理多个xml文件吗?
- generics - 与方法引用配对的泛型类型
- javascript - 如何正确实现 videojs-dvrseekbar 插件?
- caching - CachePut 跳过必填字段