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怎樣出現。