对于我的Android项目,我需要构建一个自定义布局管理器。 因此,我查看了http://wiresareobsolete.com/2014/09/building-a-recyclerview-layoutmanager-part-1/和https://developer.inthepocket.mobi/2017/01/04/android-layoutmanager-part-1/
上的帖子但是我在理解scrollVerticallyBy()
(或scrollHorizontally()
)方法的内部实现时遇到了问题。
从上述文章中我得到的是布局管理器有责任移动视图。为此,RecyclerView
为我们提供了可以进行移动的前期信息。该信息是dy
(或dx
)参数,它告诉我们框架认为我们应该改变观点的程度。
然后,在scrollXBy()
方法内部,使用该增量值,我们必须确定某些边界条件。
返回值指定框架我们实际行进/移动的距离。
我不理解这些方法中的计算。来自https://developer.inthepocket.mobi/2017/01/04/android-layoutmanager-part-1/的以下代码段将我的问题显示为注释:
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
if (getChildCount() == 0) {
return 0;
}
int scrolled = 0;
final int left = getPaddingLeft();
final int right = getWidth() - getPaddingRight();
// why we check if dy is less than 0 ?
if (dy < 0) {
while (scrolled > dy) {
// that is clear, we obtain the view at index 0
final View topView = getChildAt(0);
// getDecoratedTop() gives us the top edge but why we have a - sign ?
// why is there a 0 ? what is hangingTop representing ?
final int hangingTop = Math.max(-getDecoratedTop(topView), 0);
// why we compute scrolled - dy ?
final int scrollBy = Math.min(scrolled - dy, hangingTop);
// ok, we update our scrolled variable which should tell how far we traveled
scrolled -= scrollBy;
// that call is clear. It shifts our views by the given value
offsetChildrenVertical(scrollBy);
// ???
if (mFirstPosition > 0 && scrolled > dy) {
mFirstPosition--;
View v = recycler.getViewForPosition(mFirstPosition);
addView(v, 0);
measureChildWithMargins(v, 0, 0);
final int bottom = getDecoratedTop(topView);
final int top = bottom - getDecoratedMeasuredHeight(v);
layoutDecorated(v, left, top, right, bottom);
} else {
break;
}
}
}
// I could ask the same questions about the lines of this block, too
else if (dy > 0) {
final int parentHeight = getHeight();
while (scrolled < dy) {
final View bottomView = getChildAt(getChildCount() - 1);
final int hangingBottom =
Math.max(getDecoratedBottom(bottomView) - parentHeight, 0);
final int scrollBy = -Math.min(dy - scrolled, hangingBottom);
scrolled -= scrollBy;
offsetChildrenVertical(scrollBy);
if (scrolled < dy && state.getItemCount() > mFirstPosition + getChildCount()) {
View v = recycler.getViewForPosition(mFirstPosition + getChildCount());
final int top = getDecoratedBottom(getChildAt(getChildCount() - 1));
addView(v);
measureChildWithMargins(v, 0, 0);
final int bottom = top + getDecoratedMeasuredHeight(v);
layoutDecorated(v, left, top, right, bottom);
} else {
break;
}
}
}
recycleViewsOutOfBounds(recycler);
return scrolled;
}
因此,总而言之:我可以理解这些方法的用途等等,但是我无法弄清楚它们是如何进行计算的等等。