Android StaggedGridLayoutManager返回错误的垂直滚动偏移
我所做的几乎与此处()相同,但在选项卡中使用了RecyclerView 一个选项卡中的RecyclerView包含高度较大的项目,第一个项目在标题下并不总是完全可见。 在某个时候,我调用了RecyclerView的computeVerticalScrollOffset()(它调用了StaggedGridLayoutManager的方法),它返回了完全错误的值。若我改变页眉高度以使第一项完全可见,那个么我得到的值是正确的 是否有任何已知的解决方案/修复方案Android StaggedGridLayoutManager返回错误的垂直滚动偏移,android,android-recyclerview,Android,Android Recyclerview,我所做的几乎与此处()相同,但在选项卡中使用了RecyclerView 一个选项卡中的RecyclerView包含高度较大的项目,第一个项目在标题下并不总是完全可见。 在某个时候,我调用了RecyclerView的computeVerticalScrollOffset()(它调用了StaggedGridLayoutManager的方法),它返回了完全错误的值。若我改变页眉高度以使第一项完全可见,那个么我得到的值是正确的 是否有任何已知的解决方案/修复方案 另外,我还使用LinearLayoutM
另外,我还使用LinearLayoutManager,即使标题下的第一项不完全可见,也始终可以获得正确的值
@Override
public int computeVerticalScrollOffset() {
return mLayout.canScrollVertically() ? mLayout.computeVerticalScrollOffset(mState) : 0;
}
mLayout是LayoutManager
的一个实例。在我们的例子中,它应该属于StaggedGridLayoutManager
。让我们看看那里:
@Override
public int computeVerticalScrollOffset(RecyclerView.State state) {
return computeScrollOffset(state);
}
那么这里:
private int computeScrollOffset(RecyclerView.State state) {
if (getChildCount() == 0) {
return 0;
}
ensureOrientationHelper();
return ScrollbarHelper.computeScrollOffset(state, mPrimaryOrientation,
findFirstVisibleItemClosestToStart(!mSmoothScrollbarEnabled, true)
, findFirstVisibleItemClosestToEnd(!mSmoothScrollbarEnabled, true),
this, mSmoothScrollbarEnabled, mShouldReverseLayout);
}
最后我们转到ScrollbarHelper.computeScrollOffset:
/**
* @param startChild View closest to start of the list. (top or left)
* @param endChild View closest to end of the list (bottom or right)
*/
static int computeScrollOffset(RecyclerView.State state, OrientationHelper orientation,
View startChild, View endChild, RecyclerView.LayoutManager lm,
boolean smoothScrollbarEnabled, boolean reverseLayout) {
if (lm.getChildCount() == 0 || state.getItemCount() == 0 || startChild == null ||
endChild == null) {
return 0;
}
final int minPosition = Math.min(lm.getPosition(startChild),
lm.getPosition(endChild));
final int maxPosition = Math.max(lm.getPosition(startChild),
lm.getPosition(endChild));
final int itemsBefore = reverseLayout
? Math.max(0, state.getItemCount() - maxPosition - 1)
: Math.max(0, minPosition);
if (!smoothScrollbarEnabled) {
return itemsBefore;
}
final int laidOutArea = Math.abs(orientation.getDecoratedEnd(endChild) -
orientation.getDecoratedStart(startChild));
final int itemRange = Math.abs(lm.getPosition(startChild) -
lm.getPosition(endChild)) + 1;
final float avgSizePerRow = (float) laidOutArea / itemRange;
return Math.round(itemsBefore * avgSizePerRow + (orientation.getStartAfterPadding()
- orientation.getDecoratedStart(startChild)));
}
我们应该关注最后一句话。此方法返回由items*avgHeight计算的偏移量,当我们的项目具有不同的高度时,该值不准确
因此,当我们使用GridLayoutManager
的LinearLayoutManager
时,由于确认了每行的高度,computeVerticalScrollOffset()
将返回正确的距离。然而,不幸的是,当我们使用StaggedGridLayoutManager
时,我们无法通过它获得准确的滚动偏移量
p.S我知道它不正确的原因,但我不知道如何获得正确的滚动距离。如果有人知道,请访问:并发布您的答案 我认为错误在于computeScrollOffset()函数参数中使用的findFirstVisiblePosition()和findLastVisiblePosition()。即使我使用几乎相等的行高,computeVerticalScrollOffset()也会返回非常奇怪的数字。 如果我们用实际有效的recyclerView.getChildAt(0)和recyclerView.getChildAt(recyclerView.getChildCount()-1)替换它们 因此,我们可以编写自己的函数:
View firstItemView = recyclerView.getChildAt(0);
View lastItemView = recyclerView.getChildAt(recyclerView.getChildCount() - 1);
int firstItem = recyclerView.getChildLayoutPosition(firstItemView);
int lastItem = recyclerView.getChildLayoutPosition(lastItemView);
int itemsBefore = firstItem;
int laidOutArea = recyclerView.getLayoutManager().getDecoratedBottom(lastItemView) - recyclerView.getLayoutManager().getDecoratedTop(firstItemView);
int itemRange = lastItem - firstItem + 1;
float avgSizePerRow = (float) laidOutArea / itemRange;
int offset = (int) (itemsBefore * avgSizePerRow + recyclerView.getLayoutManager().getPaddingTop() - recyclerView.getLayoutManager().getDecoratedTop(firstItemView));