finalint measureHeightOfChildren(int widthMeasureSpec, int startPosition, int endPosition, finalint maxHeight, int disallowPartialChildPosition) {
final ListAdapter adapter = mAdapter; if (adapter == null) { return mListPadding.top + mListPadding.bottom; } int returnedHeight = mListPadding.top + mListPadding.bottom; ... View child; // onMeasure传递过来的endPosition==NO_POSITION,也就是-1,则令endPosition取数据源的adapter.getCount() - 1 endPosition = (endPosition == NO_POSITION) ? adapter.getCount() - 1 : endPosition; final AbsListView.RecycleBin recycleBin = mRecycler; finalboolean recyle = recycleOnMeasure(); finalboolean[] isScrap = mIsScrap; /* * 从起始位置0(onMeasure中传入的是0)开始,循环地创建ItemView,并累加ItemView的高度,当高度和超过onMeasure传递过来的maxHeight(其实是测量规格中的size)时,跳出循环 */ for (i = startPosition; i <= endPosition; ++i) { child = obtainView(i, isScrap);
measureScrapChild(child, i, widthMeasureSpec);
if (i > 0) { // 计算高度的时候还需将ItemView间的分隔距离考虑进来 returnedHeight += dividerHeight; }
// Recycle the view before we possibly return from the method if (recyle && recycleBin.shouldRecycleViewType( ((LayoutParams) child.getLayoutParams()).viewType)) { /* * 注意,这里addScrapView方法传入的第二个参数也就是position为-1, * 由于Layout过程中调用getScrapView方法时传入的position>=0, * 故position为-1的ScrapView都不会被回收,读懂这句话需要了解RecycleBin类,这里暂不深究。 */ recycleBin.addScrapView(child, -1); }
returnedHeight += child.getMeasuredHeight(); // 循环提前终止条件 if (returnedHeight >= maxHeight) { // 加上第i个的高度后returnedHeight已经超过了maxHeight,故高度探测应结束,说明最多只能容纳到第i个item return (disallowPartialChildPosition >= 0) // Disallowing is enabled (> -1) && (i > disallowPartialChildPosition) // We've past the min pos && (prevHeightWithoutPartialChild > 0) // We have a prev height && (returnedHeight != maxHeight) // 第i个Item不能显示完全,即超出容器 ? prevHeightWithoutPartialChild : maxHeight; }
if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) { prevHeightWithoutPartialChild = returnedHeight; } } return returnedHeight; }
A parent view may call measure() more than once on its children. For example, the parent may measure each child once with unspecified dimensions to find out how big they want to be, then call measure() on them again with actual numbers if the sum of all the children’s unconstrained sizes is too big or too small.