4.2 getChildColumn 和 setPositionColumn :
java
mPostionData 是一个SparseArray , 记录了每一个 item 对应的 GridItemRecord对象,app
//StaggeredGridView.java private int getChildColumn(final int itemPos, final boolean flowDown) {// (0, true) // do we already have a column for this child position? int column = getPositionColumn(itemPos); // returned -1 for the current case // we don't have the column or it no longer fits in our grid final int columnCount = mColumnCount; if (column < 0 || column >= columnCount) { // if we're going down - // get the highest positioned (lowest value) // column bottom if (flowDown) { column = getHighestPositionedBottomColumn(); // so we got here , and returned 0 for the current case } else { column = getLowestPositionedTopColumn(); } } return column; } private int getPositionColumn(final int itemPos) { GridItemRecord rec = mPositionData.get(position, null); return rec != null ? rec.column : -1; } private int getHighestPositionedBottomColumn() { int columnFound = 0; int highestPositionedBottom = Integer.MAX_VALUE; // the highest positioned bottom is the one with the lowest value :D for (int i = 0; i < mColumnCount; i++) { int bottom = mColumnBottoms[i]; if (bottom < highestPositionedBottom) { highestPositionedBottom = bottom; columnFound = i; } } return columnFound; }
4.2' setPositionColumnide
//StaggeredGridView.java private void setPositionColumn(final int position, final int column) {// (0, 0) GridItemRecord rec = getOrCreateRecord(position); rec.column = column; // colunm is set to 0, now mPostionData has one element :D } private GridItemRecord getOrCreateRecord(final int position) {//(0) GridItemRecord rec = mPositionData.get(position, null); //mPositionData is empty now , so null returned if (rec == null) { rec = new GridItemRecord(); // create one mPositionData.append(position, rec); } return rec; }
而后返回到4.1 --> 4 , 新的view 被建立(child) , 而后setupChild ---> 步骤5:this
5, setupChild (child, 0, topPadding , true, false, false):spa
执行 addViewToParent, code
needToMeasure 为 true;mMotionPostion 为 0orm
而后measure , layout, 此时 listview已经有了一个 child. :D对象
//ExtendableListView.java private void setupChild(View child, int itemPos, int y, boolean flowDown, boolean selected, boolean recycled) { final boolean isSelected = false; // TODO : selected && shouldShowSelector(); final boolean updateChildSelected = isSelected != child.isSelected();// false final int mode = mTouchMode; final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLLING && mMotionPosition == itemPos; // 0 now final boolean updateChildPressed = isPressed != child.isPressed(); final boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested(); //true int itemViewType = mAdapter.getItemViewType(itemPos); LayoutParams layoutParams; if (itemViewType == ITEM_VIEW_TYPE_HEADER_OR_FOOTER) { layoutParams = generateWrapperLayoutParams(child); } else { layoutParams = generateChildLayoutParams(child); } layoutParams.viewType = itemViewType; layoutParams.position = position; if (recycled || (layoutParams.recycledHeaderFooter && layoutParams.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER)) { attachViewToParent(child, flowDown ? -1 : 0, layoutParams); } else { if (layoutParams.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER) { layoutParams.recycledHeaderFooter = true; } addViewInLayout(child, flowDown ? -1 : 0, layoutParams, true); //got here , added a view but don't layout it } if (updateChildSelected) { child.setSelected(isSelected); } if (updateChildPressed) { child.setPressed(isPressed); } if (needToMeasure) { onMeasureChild(child, layoutParams); } else { cleanupLayoutState(child); } final int w = child.getMeasuredWidth(); final int h = child.getMeasuredHeight(); final int childTop = flowDown ? y : y - h; final int childrenLeft = getChildLeft(itemPos); if (needToMeasure) { final int childRight = childrenLeft + w; final int childBottom = childTop + h; onLayoutChild(child, itemPos, flowDown, childrenLeft, childTop, childRight, childBottom); } else { onOffsetChild(child, itemPos, flowDown, childrenLeft, childTop); } }
上面有几个点: generateChildLayoutParams( child ) , getChildLeft 、onLayoutChild .element
GridLayoutParams 多了一个column变量, 记录该child所属的列,onMeasureChild 将宽度限定为mColumnWidth , 并记录了heightRatioget
@Override protected void onMeasureChild(final View child, final LayoutParams layoutParams) { final int viewType = layoutParams.viewType; final int position = layoutParams.position; if (viewType == ITEM_VIEW_TYPE_HEADER_OR_FOOTER || viewType == ITEM_VIEW_TYPE_IGNORE) { super.onMeasureChild(child, layoutParams); } else { // measure it to the width of our column. int childWidthSpec = MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY); int childHeightSpec; if (layoutParams.height > 0) { childHeightSpec = MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY); } else { childHeightSpec = MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.UNSPECIFIED); } child.measure(childWidthSpec, childHeightSpec); } final int childHeight = getChildHeight(child); setPositionHeightRatio(position, childHeight); } private void setPositionHeightRatio(final int itemPos, final int height) { //(0 ,childHeight ) GridItemRecord rec = getOrCreateRecord(itemPos); rec.heightRatio = (double) height / (double) mColumnWidth; }
getChildLeft: mColumnLefts[] 记录了每一列左侧的开始移位
@Override protected int getChildLeft(final int position) { if (isHeaderOrFooter(position)) { return super.getChildLeft(position); } else { final int column = getPositionColumn(position); return mColumnLefts[column]; } } private int getPositionColumn(final int itemPos) { GridItemRecord rec = mPositionData.get(itemPos, null); return rec != null ? rec.column : -1; }
另外, 在onLayoutChild 中调用了layoutGridChild , 这个方法完成了child的layout过程,而且更新了 mColumnTops[] 、mColumnTops[] 记录。
到此,listview中已经有了第一个child, 而后回到步骤4的结尾, 而后回到步骤3的 while循环中: 此时makeAndAddView已经成功地往listview中加入了第一个view, 接下来要加入第二个、第三个...第X个child, 假设有listview有两列(能够设置,列越多,mColumnWidth就越小),咱们记下makeAndView结束时的状态,而后看第二个child view怎样出现。