StaggeredGridView 实现分析--首次填充过程(一)续

4.2 getChildColumn 和 setPositionColumn :

mPostionData 是一个SparseArray , 记录了每个 item 对应的 GridItemRecord对象,

//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' setPositionColumn

  //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:


5, setupChild (child, 0, topPadding , true, false, false):

执行 addViewToParent, 

needToMeasure 为 true;mMotionPostion 为 0

然后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 .

GridLayoutParams 多了一个column变量, 记录该child所属的列,onMeasureChild 将宽度限定为mColumnWidth , 并记录了heightRatio

@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怎样出现。


转载于:https://my.oschina.net/u/255456/blog/344770

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值