我做的几乎与此处(https://github.com/kmshack/Android-ParallaxHeaderViewPager)相同,但在选项卡中使用了RecyclerView。
在一个标签中的RecyclerView具有较大高度的项目,并且第一个在标题下并不总是完全可见。 在某些时候,我调用RecyclerView的computeVerticalScrollOffset()(调用StaggeredGridLayoutManager的方法),它返回完全错误的值。如果我更改标题高度以使第一个项目完全可见我正在获得正确的值。
是否有任何已知的解决方案/解决方案?
P.S。我也使用LinearLayoutManager并始终获得正确的值,即使第一项在标题
下不完全可见答案 0 :(得分:2)
我认为错误在于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));
答案 1 :(得分:0)
让我们按照RecyclerView
:
@Override
public int computeVerticalScrollOffset() {
return mLayout.canScrollVertically() ? mLayout.computeVerticalScrollOffset(mState) : 0;
}
mLayout是LayoutManager
的一个实例。在我们的例子中,它应该属于StaggeredGridLayoutManager
。我们来看看:
@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)));
}
我们应该关注最后的陈述。此方法返回由* avgHeight项计算的偏移量,当我们的项目具有各种高度时,这是不准确的。
因此,当我们使用LinearLayoutManager
GridLayoutManager
时,由于确认了每行的高度,computeVerticalScrollOffset()
将返回正确的距离。但是,遗憾的是,当我们使用StaggeredGridLayoutManager
时,我们无法通过它获得准确的滚动偏移。
P.S 我知道它不正确的原因,但我不知道如何获得正确的滚动距离。如果有人知道,请访问:How to get correct scroll distance of RecyclerView when using a StaggeredGridLayoutManager?并发布您的回答。