Example usage for android.view View measure

List of usage examples for android.view View measure

Introduction

In this page you can find the example usage for android.view View measure.

Prototype

public final void measure(int widthMeasureSpec, int heightMeasureSpec) 

Source Link

Document

This is called to find out how big a view should be.

Usage

From source file:com.example.mvpdemo.widget.NarrowParentViewPager.java

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {

    Log.i("xx", "================= onLayout =================");

    final int count = getChildCount();
    int width = r - l;
    int height = b - t;
    int paddingLeft = getPaddingLeft();
    int paddingTop = getPaddingTop();
    int paddingRight = getPaddingRight();
    int paddingBottom = getPaddingBottom();
    final int scrollX = getScrollX();

    int decorCount = 0;

    // First pass - decor views. We need to do this in two passes so that
    // we have the proper offsets for non-decor views later.
    for (int i = 0; i < count; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() != GONE) {
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            int childLeft = 0;
            int childTop = 0;
            if (lp.isDecor) {
                final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
                final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK;
                switch (hgrav) {
                default:
                    childLeft = paddingLeft;
                    break;
                case Gravity.LEFT:
                    childLeft = paddingLeft;
                    paddingLeft += child.getMeasuredWidth();
                    break;
                case Gravity.CENTER_HORIZONTAL:
                    childLeft = Math.max((width - child.getMeasuredWidth()) / 2, paddingLeft);
                    break;
                case Gravity.RIGHT:
                    childLeft = width - paddingRight - child.getMeasuredWidth();
                    paddingRight += child.getMeasuredWidth();
                    break;
                }/*from w  ww .  jav a 2s . c  o m*/
                switch (vgrav) {
                default:
                    childTop = paddingTop;
                    break;
                case Gravity.TOP:
                    childTop = paddingTop;
                    paddingTop += child.getMeasuredHeight();
                    break;
                case Gravity.CENTER_VERTICAL:
                    childTop = Math.max((height - child.getMeasuredHeight()) / 2, paddingTop);
                    break;
                case Gravity.BOTTOM:
                    childTop = height - paddingBottom - child.getMeasuredHeight();
                    paddingBottom += child.getMeasuredHeight();
                    break;
                }
                childLeft += scrollX;
                child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(),
                        childTop + child.getMeasuredHeight());
                decorCount++;
            }
        }
    }

    final int childWidth = width - paddingLeft - paddingRight - 2 * (OFFSET);
    // Page views. Do this once we have the right padding offsets from above.
    for (int i = 0; i < count; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() != GONE && (child == mCurrent && mDragDistance == 0 || child != mCurrent)) {
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            ItemInfo ii;
            if (!lp.isDecor && (ii = infoForChild(child)) != null) {

                Log.i("Narrow", "INDEX = " + i + "   offset = " + ii.offset);

                int loff = (int) (childWidth * ii.offset);
                int childLeft = paddingLeft + loff;
                int childTop = paddingTop;
                if (lp.needsMeasure) {
                    // This was added during layout and needs measurement.
                    // Do it now that we know what we're working with.
                    lp.needsMeasure = false;
                    final int widthSpec = MeasureSpec.makeMeasureSpec((int) (childWidth * lp.widthFactor),
                            MeasureSpec.EXACTLY);
                    final int heightSpec = MeasureSpec
                            .makeMeasureSpec((int) (height - paddingTop - paddingBottom), MeasureSpec.EXACTLY);
                    child.measure(widthSpec, heightSpec);
                }
                if (DEBUG)
                    Log.v(TAG, "Positioning #" + i + " " + child + " f=" + ii.object + ":" + childLeft + ","
                            + childTop + " " + child.getMeasuredWidth() + "x" + child.getMeasuredHeight());
                child.layout(childLeft + OFFSET + PADDING,
                        childTop + (int) ((OFFSET + PADDING) * (float) getHeight() / getWidth()),
                        (int) (childLeft + child.getMeasuredWidth()) + OFFSET + PADDING,
                        childTop + child.getMeasuredHeight());
            }
        }
    }
    mTopPageBounds = paddingTop;
    mBottomPageBounds = height - paddingBottom;
    mDecorChildCount = decorCount;

    if (mFirstLayout) {
        scrollToItem(mCurItem, false, 0, false);
    }
    mFirstLayout = false;
}

From source file:com.aliasapps.seq.scroller.TwoWayView.java

private void measureScrapChild(View scrapChild, int position, int secondaryMeasureSpec) {
    LayoutParams lp = (LayoutParams) scrapChild.getLayoutParams();
    if (lp == null) {
        lp = generateDefaultLayoutParams();
        scrapChild.setLayoutParams(lp);//ww w  .  jav  a2 s  .  c om
    }

    lp.viewType = mAdapter.getItemViewType(position);
    lp.forceAdd = true;

    final int widthMeasureSpec;
    final int heightMeasureSpec;
    if (mIsVertical) {
        widthMeasureSpec = secondaryMeasureSpec;
        heightMeasureSpec = getChildHeightMeasureSpec(lp);
    } else {
        widthMeasureSpec = getChildWidthMeasureSpec(lp);
        heightMeasureSpec = secondaryMeasureSpec;
    }

    scrapChild.measure(widthMeasureSpec, heightMeasureSpec);
}

From source file:android.improving.utils.views.cardsview.OrientedViewPager.java

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = getChildCount();
    int width = r - l;
    int height = b - t;
    int paddingLeft = getPaddingLeft();
    int paddingTop = getPaddingTop();
    int paddingRight = getPaddingRight();
    int paddingBottom = getPaddingBottom();
    final int scroll = (mOrientation == Orientation.VERTICAL) ? getScrollY() : getScrollX();

    int decorCount = 0;

    // First pass - decor views. We need to do this in two passes so that
    // we have the proper offsets for non-decor views later.
    for (int i = 0; i < count; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() != GONE) {
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            int childLeft = 0;
            int childTop = 0;
            if (lp.isDecor) {
                final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
                final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK;
                switch (hgrav) {
                default:
                    childLeft = paddingLeft;
                    break;
                case Gravity.LEFT:
                    childLeft = paddingLeft;
                    paddingLeft += child.getMeasuredWidth();
                    break;
                case Gravity.CENTER_HORIZONTAL:
                    childLeft = Math.max((width - child.getMeasuredWidth()) / 2, paddingLeft);
                    break;
                case Gravity.RIGHT:
                    childLeft = width - paddingRight - child.getMeasuredWidth();
                    paddingRight += child.getMeasuredWidth();
                    break;
                }/*from  ww w. ja v  a2  s  .  c o  m*/
                switch (vgrav) {
                default:
                    childTop = paddingTop;
                    break;
                case Gravity.TOP:
                    childTop = paddingTop;
                    paddingTop += child.getMeasuredHeight();
                    break;
                case Gravity.CENTER_VERTICAL:
                    childTop = Math.max((height - child.getMeasuredHeight()) / 2, paddingTop);
                    break;
                case Gravity.BOTTOM:
                    childTop = height - paddingBottom - child.getMeasuredHeight();
                    paddingBottom += child.getMeasuredHeight();
                    break;
                }
                if (mOrientation == Orientation.VERTICAL) {
                    childTop += scroll;
                } else {
                    childLeft += scroll;
                }
                child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(),
                        childTop + child.getMeasuredHeight());
                decorCount++;
            }
        }
    }

    final int childSize = (mOrientation == Orientation.VERTICAL) ? height - paddingTop - paddingBottom
            : width - paddingLeft - paddingRight;
    // Page views. Do this once we have the right padding offsets from above.
    for (int i = 0; i < count; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() != GONE) {
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            ItemInfo ii;
            if (!lp.isDecor && (ii = infoForChild(child)) != null) {
                int topLeftoff = (int) (childSize * ii.offset);
                int childLeft;
                int childTop;
                if (mOrientation == Orientation.VERTICAL) {
                    childLeft = paddingLeft;
                    childTop = paddingTop + topLeftoff;
                    if (lp.needsMeasure) {
                        // This was added during layout and needs measurement.
                        // Do it now that we know what we're working with.
                        lp.needsMeasure = false;
                        final int widthSpec = MeasureSpec.makeMeasureSpec(
                                (int) (width - paddingLeft - paddingRight), MeasureSpec.EXACTLY);
                        final int heightSpec = MeasureSpec.makeMeasureSpec((int) (childSize * lp.heightFactor),
                                MeasureSpec.EXACTLY);
                        child.measure(widthSpec, heightSpec);
                    }
                } else {
                    childLeft = paddingLeft + topLeftoff;
                    childTop = paddingTop;
                    if (lp.needsMeasure) {
                        // This was added during layout and needs measurement.
                        // Do it now that we know what we're working with.
                        lp.needsMeasure = false;
                        final int widthSpec = MeasureSpec.makeMeasureSpec((int) (childSize * lp.widthFactor),
                                MeasureSpec.EXACTLY);
                        final int heightSpec = MeasureSpec.makeMeasureSpec(
                                (int) (height - paddingTop - paddingBottom), MeasureSpec.EXACTLY);
                        child.measure(widthSpec, heightSpec);
                    }
                }
                if (DEBUG)
                    Log.v(TAG, "Positioning #" + i + " " + child + " f=" + ii.object + ":" + childLeft + ","
                            + childTop + " " + child.getMeasuredWidth() + "x" + child.getMeasuredHeight());
                child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(),
                        childTop + child.getMeasuredHeight());
            }
        }
    }
    mTopLeftPageBounds = (mOrientation == Orientation.VERTICAL) ? paddingLeft : paddingTop;
    mBottomRightPageBounds = (mOrientation == Orientation.VERTICAL) ? width - paddingRight
            : height - paddingBottom;
    mDecorChildCount = decorCount;

    if (mFirstLayout) {
        scrollToItem(mCurItem, false, 0, false);
    }
    mFirstLayout = false;
}

From source file:cn.androidy.materialdesignsample.ryanharterviewpager.ViewPager.java

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = getChildCount();
    int width = r - l;
    int height = b - t;
    int paddingLeft = getPaddingLeft();
    int paddingTop = getPaddingTop();
    int paddingRight = getPaddingRight();
    int paddingBottom = getPaddingBottom();
    final int scrollX = getScrollX();
    final int scrollY = getScrollY();

    int decorCount = 0;

    // First pass - decor views. We need to do this in two passes so that
    // we have the proper offsets for non-decor views later.
    for (int i = 0; i < count; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() != GONE) {
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            int childLeft = 0;
            int childTop = 0;
            if (lp.isDecor) {
                final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
                final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK;
                switch (hgrav) {
                default:
                    childLeft = paddingLeft;
                    break;
                case Gravity.LEFT:
                    childLeft = paddingLeft;
                    paddingLeft += child.getMeasuredWidth();
                    break;
                case Gravity.CENTER_HORIZONTAL:
                    childLeft = Math.max((width - child.getMeasuredWidth()) / 2, paddingLeft);
                    break;
                case Gravity.RIGHT:
                    childLeft = width - paddingRight - child.getMeasuredWidth();
                    paddingRight += child.getMeasuredWidth();
                    break;
                }/*from   w w w  .  j a va2s  . co  m*/
                switch (vgrav) {
                default:
                    childTop = paddingTop;
                    break;
                case Gravity.TOP:
                    childTop = paddingTop;
                    paddingTop += child.getMeasuredHeight();
                    break;
                case Gravity.CENTER_VERTICAL:
                    childTop = Math.max((height - child.getMeasuredHeight()) / 2, paddingTop);
                    break;
                case Gravity.BOTTOM:
                    childTop = height - paddingBottom - child.getMeasuredHeight();
                    paddingBottom += child.getMeasuredHeight();
                    break;
                }
                if (isOrientationHorizontal()) {
                    childLeft += scrollX;
                } else {
                    childTop += scrollY;
                }
                child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(),
                        childTop + child.getMeasuredHeight());
                decorCount++;
            }
        }
    }

    int childSize = 0;
    if (isOrientationHorizontal()) {
        childSize = width - paddingLeft - paddingRight;
    } else {
        childSize = height - paddingTop - paddingBottom;
    }
    // Page views. Do this once we have the right padding offsets from above.
    for (int i = 0; i < count; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() != GONE) {
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            ItemInfo ii;
            if (!lp.isDecor && (ii = infoForChild(child)) != null) {
                int loff = (int) (childSize * ii.offset);
                int childLeft = paddingLeft + (isOrientationHorizontal() ? loff : 0);
                int childTop = paddingTop + (isOrientationHorizontal() ? 0 : loff);
                if (lp.needsMeasure) {
                    // This was added during layout and needs measurement.
                    // Do it now that we know what we're working with.
                    lp.needsMeasure = false;
                    int widthSpec = 0, heightSpec = 0;
                    if (isOrientationHorizontal()) {
                        widthSpec = MeasureSpec.makeMeasureSpec((int) (childSize * lp.sizeFactor),
                                MeasureSpec.EXACTLY);
                        heightSpec = MeasureSpec.makeMeasureSpec((int) (height - paddingTop - paddingBottom),
                                MeasureSpec.EXACTLY);
                    } else {
                        widthSpec = MeasureSpec.makeMeasureSpec((int) (width - paddingLeft - paddingRight),
                                MeasureSpec.EXACTLY);
                        heightSpec = MeasureSpec.makeMeasureSpec((int) (childSize * lp.sizeFactor),
                                MeasureSpec.EXACTLY);
                    }
                    child.measure(widthSpec, heightSpec);
                }
                if (DEBUG)
                    Log.v(TAG, "Positioning #" + i + " " + child + " f=" + ii.object + ":" + childLeft + ","
                            + childTop + " " + child.getMeasuredWidth() + "x" + child.getMeasuredHeight());
                child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(),
                        childTop + child.getMeasuredHeight());
            }
        }
    }
    mLeftPageBounds = paddingLeft;
    mTopPageBounds = paddingTop;
    mRightPageBounds = width - paddingRight;
    mBottomPageBounds = height - paddingBottom;
    mDecorChildCount = decorCount;

    if (mFirstLayout) {
        scrollToItem(mCurItem, false, 0, false);
    }
    mFirstLayout = false;
}

From source file:com.guide.ViewPager.java

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = getChildCount();
    int width = r - l;
    int height = b - t;
    int paddingLeft = getPaddingLeft();
    int paddingTop = getPaddingTop();
    int paddingRight = getPaddingRight();
    int paddingBottom = getPaddingBottom();
    final int scrollX = getScrollX();
    final int scrollY = getScrollY();

    int decorCount = 0;

    // First pass - decor views. We need to do this in two passes so that
    // we have the proper offsets for non-decor views later.
    for (int i = 0; i < count; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() != GONE) {
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            int childLeft = 0;
            int childTop = 0;
            if (lp.isDecor) {
                final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
                final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK;
                switch (hgrav) {
                default:
                    childLeft = paddingLeft;
                    break;
                case Gravity.LEFT:
                    childLeft = paddingLeft;
                    paddingLeft += child.getMeasuredWidth();
                    break;
                case Gravity.CENTER_HORIZONTAL:
                    childLeft = Math.max((width - child.getMeasuredWidth()) / 2, paddingLeft);
                    break;
                case Gravity.RIGHT:
                    childLeft = width - paddingRight - child.getMeasuredWidth();
                    paddingRight += child.getMeasuredWidth();
                    break;
                }/*from  w w  w .j a  v a 2 s.com*/
                switch (vgrav) {
                default:
                    childTop = paddingTop;
                    break;
                case Gravity.TOP:
                    childTop = paddingTop;
                    paddingTop += child.getMeasuredHeight();
                    break;
                case Gravity.CENTER_VERTICAL:
                    childTop = Math.max((height - child.getMeasuredHeight()) / 2, paddingTop);
                    break;
                case Gravity.BOTTOM:
                    childTop = height - paddingBottom - child.getMeasuredHeight();
                    paddingBottom += child.getMeasuredHeight();
                    break;
                }
                if (isOrientationHorizontal()) {
                    childLeft += scrollX;
                } else {
                    childTop += scrollY;
                }
                child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(),
                        childTop + child.getMeasuredHeight());
                decorCount++;
            }
        }
    }

    int childSize = 0;
    if (isOrientationHorizontal()) {
        childSize = width - paddingLeft - paddingRight;
    } else {
        childSize = height - paddingTop - paddingBottom;
    }
    // Page views. Do this once we have the right padding offsets from
    // above.
    for (int i = 0; i < count; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() != GONE) {
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            ItemInfo ii;
            if (!lp.isDecor && (ii = infoForChild(child)) != null) {
                int loff = (int) (childSize * ii.offset);
                int childLeft = paddingLeft + (isOrientationHorizontal() ? loff : 0);
                int childTop = paddingTop + (isOrientationHorizontal() ? 0 : loff);
                if (lp.needsMeasure) {
                    // This was added during layout and needs measurement.
                    // Do it now that we know what we're working with.
                    lp.needsMeasure = false;
                    int widthSpec = 0, heightSpec = 0;
                    if (isOrientationHorizontal()) {
                        widthSpec = MeasureSpec.makeMeasureSpec((int) (childSize * lp.sizeFactor),
                                MeasureSpec.EXACTLY);
                        heightSpec = MeasureSpec.makeMeasureSpec((int) (height - paddingTop - paddingBottom),
                                MeasureSpec.EXACTLY);
                    } else {
                        widthSpec = MeasureSpec.makeMeasureSpec((int) (width - paddingLeft - paddingRight),
                                MeasureSpec.EXACTLY);
                        heightSpec = MeasureSpec.makeMeasureSpec((int) (childSize * lp.sizeFactor),
                                MeasureSpec.EXACTLY);
                    }
                    child.measure(widthSpec, heightSpec);
                }
                if (DEBUG)
                    Log.v(TAG, "Positioning #" + i + " " + child + " f=" + ii.object + ":" + childLeft + ","
                            + childTop + " " + child.getMeasuredWidth() + "x" + child.getMeasuredHeight());
                child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(),
                        childTop + child.getMeasuredHeight());
            }
        }
    }
    mLeftPageBounds = paddingLeft;
    mTopPageBounds = paddingTop;
    mRightPageBounds = width - paddingRight;
    mBottomPageBounds = height - paddingBottom;
    mDecorChildCount = decorCount;

    if (mFirstLayout) {
        scrollToItem(mCurItem, false, 0, false);
    }
    mFirstLayout = false;
}

From source file:com.actionbarsherlock.internal.view.menu.ActionMenuView.java

private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) {
    // We already know the width mode is EXACTLY if we're here.
    final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    final int widthPadding = getPaddingLeft() + getPaddingRight();
    final int heightPadding = getPaddingTop() + getPaddingBottom();

    widthSize -= widthPadding;//from   ww w.jav  a  2s .  co m

    // Divide the view into cells.
    final int cellCount = widthSize / mMinCellSize;
    final int cellSizeRemaining = widthSize % mMinCellSize;

    if (cellCount == 0) {
        // Give up, nothing fits.
        setMeasuredDimension(widthSize, 0);
        return;
    }

    final int cellSize = mMinCellSize + cellSizeRemaining / cellCount;

    int cellsRemaining = cellCount;
    int maxChildHeight = 0;
    int maxCellsUsed = 0;
    int expandableItemCount = 0;
    int visibleItemCount = 0;
    boolean hasOverflow = false;

    // This is used as a bitfield to locate the smallest items present. Assumes childCount < 64.
    long smallestItemsAt = 0;

    final int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() == GONE)
            continue;

        final boolean isGeneratedItem = child instanceof ActionMenuItemView;
        visibleItemCount++;

        if (isGeneratedItem) {
            // Reset padding for generated menu item views; it may change below
            // and views are recycled.
            child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0);
        }

        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
        lp.expanded = false;
        lp.extraPixels = 0;
        lp.cellsUsed = 0;
        lp.expandable = false;
        lp.leftMargin = 0;
        lp.rightMargin = 0;
        lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText();

        // Overflow always gets 1 cell. No more, no less.
        final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining;

        final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable, heightMeasureSpec,
                heightPadding);

        maxCellsUsed = Math.max(maxCellsUsed, cellsUsed);
        if (lp.expandable)
            expandableItemCount++;
        if (lp.isOverflowButton)
            hasOverflow = true;

        cellsRemaining -= cellsUsed;
        maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
        if (cellsUsed == 1)
            smallestItemsAt |= (1 << i);
    }

    // When we have overflow and a single expanded (text) item, we want to try centering it
    // visually in the available space even though overflow consumes some of it.
    final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2;

    // Divide space for remaining cells if we have items that can expand.
    // Try distributing whole leftover cells to smaller items first.

    boolean needsExpansion = false;
    while (expandableItemCount > 0 && cellsRemaining > 0) {
        int minCells = Integer.MAX_VALUE;
        long minCellsAt = 0; // Bit locations are indices of relevant child views
        int minCellsItemCount = 0;
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();

            // Don't try to expand items that shouldn't.
            if (!lp.expandable)
                continue;

            // Mark indices of children that can receive an extra cell.
            if (lp.cellsUsed < minCells) {
                minCells = lp.cellsUsed;
                minCellsAt = 1 << i;
                minCellsItemCount = 1;
            } else if (lp.cellsUsed == minCells) {
                minCellsAt |= 1 << i;
                minCellsItemCount++;
            }
        }

        // Items that get expanded will always be in the set of smallest items when we're done.
        smallestItemsAt |= minCellsAt;

        if (minCellsItemCount > cellsRemaining)
            break; // Couldn't expand anything evenly. Stop.

        // We have enough cells, all minimum size items will be incremented.
        minCells++;

        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if ((minCellsAt & (1 << i)) == 0) {
                // If this item is already at our small item count, mark it for later.
                if (lp.cellsUsed == minCells)
                    smallestItemsAt |= 1 << i;
                continue;
            }

            if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) {
                // Add padding to this item such that it centers.
                child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0);
            }
            lp.cellsUsed++;
            lp.expanded = true;
            cellsRemaining--;
        }

        needsExpansion = true;
    }

    // Divide any space left that wouldn't divide along cell boundaries
    // evenly among the smallest items

    final boolean singleItem = !hasOverflow && visibleItemCount == 1;
    if (cellsRemaining > 0 && smallestItemsAt != 0
            && (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) {
        float expandCount = Long.bitCount(smallestItemsAt);

        if (!singleItem) {
            // The items at the far edges may only expand by half in order to pin to either side.
            if ((smallestItemsAt & 1) != 0) {
                LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams();
                if (!lp.preventEdgeOffset)
                    expandCount -= 0.5f;
            }
            if ((smallestItemsAt & (1 << (childCount - 1))) != 0) {
                LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams());
                if (!lp.preventEdgeOffset)
                    expandCount -= 0.5f;
            }
        }

        final int extraPixels = expandCount > 0 ? (int) (cellsRemaining * cellSize / expandCount) : 0;

        for (int i = 0; i < childCount; i++) {
            if ((smallestItemsAt & (1 << i)) == 0)
                continue;

            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (child instanceof ActionMenuItemView) {
                // If this is one of our views, expand and measure at the larger size.
                lp.extraPixels = extraPixels;
                lp.expanded = true;
                if (i == 0 && !lp.preventEdgeOffset) {
                    // First item gets part of its new padding pushed out of sight.
                    // The last item will get this implicitly from layout.
                    lp.leftMargin = -extraPixels / 2;
                }
                needsExpansion = true;
            } else if (lp.isOverflowButton) {
                lp.extraPixels = extraPixels;
                lp.expanded = true;
                lp.rightMargin = -extraPixels / 2;
                needsExpansion = true;
            } else {
                // If we don't know what it is, give it some margins instead
                // and let it center within its space. We still want to pin
                // against the edges.
                if (i != 0) {
                    lp.leftMargin = extraPixels / 2;
                }
                if (i != childCount - 1) {
                    lp.rightMargin = extraPixels / 2;
                }
            }
        }

        cellsRemaining = 0;
    }

    // Remeasure any items that have had extra space allocated to them.
    if (needsExpansion) {
        int heightSpec = MeasureSpec.makeMeasureSpec(heightSize - heightPadding, heightMode);
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();

            if (!lp.expanded)
                continue;

            final int width = lp.cellsUsed * cellSize + lp.extraPixels;
            child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightSpec);
        }
    }

    if (heightMode != MeasureSpec.EXACTLY) {
        heightSize = maxChildHeight;
    }

    setMeasuredDimension(widthSize, heightSize);
    //UNUSED mMeasuredExtraWidth = cellsRemaining * cellSize;
}

From source file:app.umitems.greenclock.widget.sgv.StaggeredGridView.java

/**
 * Measure and layout all currently visible children.
 *
 * @param queryAdapter true to requery the adapter for view data
 *///from  w  w w  .ja  va 2 s. com
final void layoutChildren(boolean queryAdapter) {
    final int paddingLeft = getPaddingLeft();
    final int paddingRight = getPaddingRight();
    final int itemMargin = mItemMargin;
    final int availableWidth = (getWidth() - paddingLeft - paddingRight - itemMargin * (mColCount - 1));
    final int colWidth = availableWidth / mColCount;
    // The availableWidth may not be divisible by mColCount. Keep the
    // remainder. It will be added to the width of the last view in the row.
    final int remainder = availableWidth % mColCount;

    boolean viewsRemovedInLayout = false;

    // If we're animating out stale views, then we want to defer recycling of views.
    final boolean deferRecyclingForAnimation = mAnimationOutMode != AnimationOut.NONE;

    if (!deferRecyclingForAnimation) {
        final int childCount = getChildCount();
        // If the latest data set has fewer data items than mFirstPosition, don't keep any
        // views on screen, and just let the layout logic below retrieve appropriate views
        // from the recycler.
        final int viewsToKeepOnScreen = (mItemCount <= mFirstPosition) ? 0 : mItemCount - mFirstPosition;

        if (childCount > viewsToKeepOnScreen) {
            // If there are more views laid out than the number of data items remaining to be
            // laid out, recycle the extraneous views.
            recycleViewsInRange(viewsToKeepOnScreen, childCount - 1);
            viewsRemovedInLayout = true;
        }
    } else {
        mViewsToAnimateOut.clear();
    }

    for (int i = 0; i < getChildCount(); i++) {
        final int position = mFirstPosition + i;
        View child = getChildAt(i);

        final int highestAvailableLayoutPosition = mItemBottoms[getNextColumnDown()];
        if (deferRecyclingForAnimation
                && (position >= mItemCount || highestAvailableLayoutPosition >= getHeight())) {
            // For the remainder of views on screen, they should not be on screen, so we can
            // skip layout.  Add them to the list of views to animate out.
            // We should only get in this position if deferRecyclingForAnimation = true,
            // otherwise, we should've recycled all views before getting into this layout loop.
            mViewsToAnimateOut.add(child);
            continue;
        }

        LayoutParams lp = null;
        int col = -1;

        if (child != null) {
            lp = (LayoutParams) child.getLayoutParams();
            col = lp.column;
        }

        final boolean needsLayout = queryAdapter || child == null || child.isLayoutRequested();
        if (queryAdapter) {
            View newView = null;
            if (deferRecyclingForAnimation) {
                // If we are deferring recycling for animation, then we don't want to pass the
                // current child in to obtainView for re-use.  obtainView() in this case should
                // try to find the view belonging to this item on screen, or populate a fresh
                // one from the recycler.
                newView = obtainView(position);
            } else {
                newView = obtainView(position, child);
            }

            // Update layout params since they may have changed
            lp = (LayoutParams) newView.getLayoutParams();

            if (newView != child) {
                if (child != null && !deferRecyclingForAnimation) {
                    mRecycler.addScrap(child);
                    removeViewInLayout(child);
                    viewsRemovedInLayout = true;
                }

                // If this view is already in the layout hierarchy, we can just detach it
                // from the parent and re-attach it at the correct index.  If the view has
                // already been removed from the layout hierarchy, getParent() == null.
                if (newView.getParent() == this) {
                    detachViewFromParent(newView);
                    attachViewToParent(newView, i, lp);
                } else {
                    addViewInLayout(newView, i, lp);
                }
            }

            child = newView;

            // Since the data has changed, we need to make sure the next child is in the
            // right column. We choose the next column down (vs. next column up) because we
            // are filling from the top of the screen downwards as we iterate through
            // visible children. (We take span into account below.)
            lp.column = getNextColumnDown();
            col = lp.column;
        }

        setReorderingArea(lp);

        final int span = Math.min(mColCount, lp.span);

        // Given the span, check if there's enough space to put this view at this column.
        // IMPORTANT Propagate the same logic to {@link #calculateLayoutStartOffsets}.
        if (span > 1) {
            if (mIsRtlLayout) {
                // For RTL layout, if the current column index is less than the span of the
                // child, then we know that there is not enough room remaining to lay this
                // child out (e.g., if col == 0, but span == 2, then laying this child down
                // at column = col would put us out of bound into a negative column index.).
                // For this scenario, reset the index back to the right-most column, and lay
                // out the child at this position where we can ensure that we can display as
                // much of the child as possible.
                if (col + 1 < span) {
                    col = mColCount - 1;
                }
            } else {
                if (mColCount - col < span) {
                    // If not, reset the col to 0.
                    col = 0;
                }
            }

            lp.column = col;
        }

        int widthSize = (colWidth * span + itemMargin * (span - 1));
        // If it is rtl, we layout the view from col to col - span +
        // 1. If it reaches the most left column, i.e. we added the
        // additional width. So the check it span == col +1
        if ((mIsRtlLayout && span == col + 1) || (!mIsRtlLayout && span + col == mColCount)) {
            widthSize += remainder;
        }
        if (needsLayout) {
            final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);

            final int heightSpec;
            if (lp.height == LayoutParams.WRAP_CONTENT) {
                heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
            } else {
                heightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
            }

            child.measure(widthSpec, heightSpec);
        }

        // Place the top of this child beneath the last by finding the lowest coordinate across
        // the columns that this child will span.  For LTR layout, we scan across from left to
        // right, and for RTL layout, we scan from right to left.
        // TODO:  Consolidate this logic with getNextRecordDown() in the future, as that method
        // already calculates the margins for us.  This will keep the implementation consistent
        // with fillUp() and fillDown().
        int childTop = mItemBottoms[col] + mItemMargin;
        if (span > 1) {
            int lowest = childTop;
            for (int spanIndex = 0; spanIndex < span; spanIndex++) {
                final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex;
                final int bottom = mItemBottoms[index] + mItemMargin;
                if (bottom > lowest) {
                    lowest = bottom;
                }
            }

            childTop = lowest;
        }

        final int childHeight = child.getMeasuredHeight();
        final int childBottom = childTop + childHeight;
        int childLeft = 0;
        int childRight = 0;
        if (mIsRtlLayout) {
            childRight = (getWidth() - paddingRight) - (mColCount - col - 1) * (colWidth + itemMargin);
            childLeft = childRight - child.getMeasuredWidth();
        } else {
            childLeft = paddingLeft + col * (colWidth + itemMargin);
            childRight = childLeft + child.getMeasuredWidth();
        }

        /*    Log.v(TAG, "[layoutChildren] height: " + childHeight
            + " top: " + childTop + " bottom: " + childBottom
            + " left: " + childLeft
            + " column: " + col
            + " position: " + position
            + " id: " + lp.id);
        */
        child.layout(childLeft, childTop, childRight, childBottom);
        if (lp.id == mFocusedChildIdToScrollIntoView) {
            child.requestFocus();
        }

        for (int spanIndex = 0; spanIndex < span; spanIndex++) {
            final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex;
            mItemBottoms[index] = childBottom;
        }

        // Whether or not LayoutRecords may have already existed for the view at this position
        // on screen, we'll update it after we lay out to ensure that the LayoutRecord
        // has the most updated information about the view at this position.  We can be assured
        // that all views before those on screen (views with adapter position < mFirstPosition)
        // have the correct LayoutRecords because calculateLayoutStartOffsets() would have
        // set them appropriately.
        LayoutRecord rec = mLayoutRecords.get(position);
        if (rec == null) {
            rec = new LayoutRecord();
            mLayoutRecords.put(position, rec);
        }

        rec.column = lp.column;
        rec.height = childHeight;
        rec.id = lp.id;
        rec.span = span;
    }

    // It appears that removeViewInLayout() does not invalidate.  So if we make use of this
    // method during layout, we should invalidate explicitly.
    if (viewsRemovedInLayout || deferRecyclingForAnimation) {
        invalidate();
    }
}

From source file:com.deepak.myclock.widget.sgv.StaggeredGridView.java

/**
 * Measure and layout all currently visible children.
 *
 * @param queryAdapter true to requery the adapter for view data
 *///from  w w w . ja  v  a 2 s .c  o m
final void layoutChildren(boolean queryAdapter) {
    final int paddingLeft = getPaddingLeft();
    final int paddingRight = getPaddingRight();
    final int itemMargin = mItemMargin;
    final int availableWidth = (getWidth() - paddingLeft - paddingRight - itemMargin * (mColCount - 1));
    final int colWidth = availableWidth / mColCount;
    // The availableWidth may not be divisible by mColCount. Keep the
    // remainder. It will be added to the width of the last view in the row.
    final int remainder = availableWidth % mColCount;

    boolean viewsRemovedInLayout = false;

    // If we're animating out stale views, then we want to defer recycling of views.
    final boolean deferRecyclingForAnimation = mAnimationOutMode != SgvAnimationHelper.AnimationOut.NONE;

    if (!deferRecyclingForAnimation) {
        final int childCount = getChildCount();
        // If the latest data set has fewer data items than mFirstPosition, don't keep any
        // views on screen, and just let the layout logic below retrieve appropriate views
        // from the recycler.
        final int viewsToKeepOnScreen = (mItemCount <= mFirstPosition) ? 0 : mItemCount - mFirstPosition;

        if (childCount > viewsToKeepOnScreen) {
            // If there are more views laid out than the number of data items remaining to be
            // laid out, recycle the extraneous views.
            recycleViewsInRange(viewsToKeepOnScreen, childCount - 1);
            viewsRemovedInLayout = true;
        }
    } else {
        mViewsToAnimateOut.clear();
    }

    for (int i = 0; i < getChildCount(); i++) {
        final int position = mFirstPosition + i;
        View child = getChildAt(i);

        final int highestAvailableLayoutPosition = mItemBottoms[getNextColumnDown()];
        if (deferRecyclingForAnimation
                && (position >= mItemCount || highestAvailableLayoutPosition >= getHeight())) {
            // For the remainder of views on screen, they should not be on screen, so we can
            // skip layout.  Add them to the list of views to animate out.
            // We should only get in this position if deferRecyclingForAnimation = true,
            // otherwise, we should've recycled all views before getting into this layout loop.
            mViewsToAnimateOut.add(child);
            continue;
        }

        LayoutParams lp = null;
        int col = -1;

        if (child != null) {
            lp = (LayoutParams) child.getLayoutParams();
            col = lp.column;
        }

        final boolean needsLayout = queryAdapter || child == null || child.isLayoutRequested();
        if (queryAdapter) {
            View newView = null;
            if (deferRecyclingForAnimation) {
                // If we are deferring recycling for animation, then we don't want to pass the
                // current child in to obtainView for re-use.  obtainView() in this case should
                // try to find the view belonging to this item on screen, or populate a fresh
                // one from the recycler.
                newView = obtainView(position);
            } else {
                newView = obtainView(position, child);
            }

            // Update layout params since they may have changed
            lp = (LayoutParams) newView.getLayoutParams();

            if (newView != child) {
                if (child != null && !deferRecyclingForAnimation) {
                    mRecycler.addScrap(child);
                    removeViewInLayout(child);
                    viewsRemovedInLayout = true;
                }

                // If this view is already in the layout hierarchy, we can just detach it
                // from the parent and re-attach it at the correct index.  If the view has
                // already been removed from the layout hierarchy, getParent() == null.
                if (newView.getParent() == this) {
                    detachViewFromParent(newView);
                    attachViewToParent(newView, i, lp);
                } else {
                    addViewInLayout(newView, i, lp);
                }
            }

            child = newView;

            // Since the data has changed, we need to make sure the next child is in the
            // right column. We choose the next column down (vs. next column up) because we
            // are filling from the top of the screen downwards as we iterate through
            // visible children. (We take span into account below.)
            lp.column = getNextColumnDown();
            col = lp.column;
        }

        setReorderingArea(lp);

        final int span = Math.min(mColCount, lp.span);

        // Given the span, check if there's enough space to put this view at this column.
        // IMPORTANT Propagate the same logic to {@link #calculateLayoutStartOffsets}.
        if (span > 1) {
            if (mIsRtlLayout) {
                // For RTL layout, if the current column index is less than the span of the
                // child, then we know that there is not enough room remaining to lay this
                // child out (e.g., if col == 0, but span == 2, then laying this child down
                // at column = col would put us out of bound into a negative column index.).
                // For this scenario, reset the index back to the right-most column, and lay
                // out the child at this position where we can ensure that we can display as
                // much of the child as possible.
                if (col + 1 < span) {
                    col = mColCount - 1;
                }
            } else {
                if (mColCount - col < span) {
                    // If not, reset the col to 0.
                    col = 0;
                }
            }

            lp.column = col;
        }

        int widthSize = (colWidth * span + itemMargin * (span - 1));
        // If it is rtl, we layout the view from col to col - span +
        // 1. If it reaches the most left column, i.e. we added the
        // additional width. So the check it span == col +1
        if ((mIsRtlLayout && span == col + 1) || (!mIsRtlLayout && span + col == mColCount)) {
            widthSize += remainder;
        }
        if (needsLayout) {
            final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);

            final int heightSpec;
            if (lp.height == LayoutParams.WRAP_CONTENT) {
                heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
            } else {
                heightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
            }

            child.measure(widthSpec, heightSpec);
        }

        // Place the top of this child beneath the last by finding the lowest coordinate across
        // the columns that this child will span.  For LTR layout, we scan across from left to
        // right, and for RTL layout, we scan from right to left.
        // TODO:  Consolidate this logic with getNextRecordDown() in the future, as that method
        // already calculates the margins for us.  This will keep the implementation consistent
        // with fillUp() and fillDown().
        int childTop = mItemBottoms[col] + mItemMargin;
        if (span > 1) {
            int lowest = childTop;
            for (int spanIndex = 0; spanIndex < span; spanIndex++) {
                final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex;
                final int bottom = mItemBottoms[index] + mItemMargin;
                if (bottom > lowest) {
                    lowest = bottom;
                }
            }

            childTop = lowest;
        }

        final int childHeight = child.getMeasuredHeight();
        final int childBottom = childTop + childHeight;
        int childLeft = 0;
        int childRight = 0;
        if (mIsRtlLayout) {
            childRight = (getWidth() - paddingRight) - (mColCount - col - 1) * (colWidth + itemMargin);
            childLeft = childRight - child.getMeasuredWidth();
        } else {
            childLeft = paddingLeft + col * (colWidth + itemMargin);
            childRight = childLeft + child.getMeasuredWidth();
        }

        /*    Log.v(TAG, "[layoutChildren] height: " + childHeight
            + " top: " + childTop + " bottom: " + childBottom
            + " left: " + childLeft
            + " column: " + col
            + " position: " + position
            + " id: " + lp.id);
        */
        child.layout(childLeft, childTop, childRight, childBottom);
        if (lp.id == mFocusedChildIdToScrollIntoView) {
            child.requestFocus();
        }

        for (int spanIndex = 0; spanIndex < span; spanIndex++) {
            final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex;
            mItemBottoms[index] = childBottom;
        }

        // Whether or not LayoutRecords may have already existed for the view at this position
        // on screen, we'll update it after we lay out to ensure that the LayoutRecord
        // has the most updated information about the view at this position.  We can be assured
        // that all views before those on screen (views with adapter position < mFirstPosition)
        // have the correct LayoutRecords because calculateLayoutStartOffsets() would have
        // set them appropriately.
        LayoutRecord rec = mLayoutRecords.get(position);
        if (rec == null) {
            rec = new LayoutRecord();
            mLayoutRecords.put(position, rec);
        }

        rec.column = lp.column;
        rec.height = childHeight;
        rec.id = lp.id;
        rec.span = span;
    }

    // It appears that removeViewInLayout() does not invalidate.  So if we make use of this
    // method during layout, we should invalidate explicitly.
    if (viewsRemovedInLayout || deferRecyclingForAnimation) {
        invalidate();
    }
}

From source file:android.support.v7.widget.LinearLayoutCompat.java

/**
 * Measures the children when the orientation of this LinearLayout is set
 * to {@link #VERTICAL}.//from   ww w.  j  av  a 2s .c  o m
 *
 * @param widthMeasureSpec Horizontal space requirements as imposed by the parent.
 * @param heightMeasureSpec Vertical space requirements as imposed by the parent.
 *
 * @see #getOrientation()
 * @see #setOrientation(int)
 * @see #onMeasure(int, int)
 */
void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
    mTotalLength = 0;
    int maxWidth = 0;
    int childState = 0;
    int alternativeMaxWidth = 0;
    int weightedMaxWidth = 0;
    boolean allFillParent = true;
    float totalWeight = 0;

    final int count = getVirtualChildCount();

    final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    final int heightMode = MeasureSpec.getMode(heightMeasureSpec);

    boolean matchWidth = false;
    boolean skippedMeasure = false;

    final int baselineChildIndex = mBaselineAlignedChildIndex;
    final boolean useLargestChild = mUseLargestChild;

    int largestChildHeight = Integer.MIN_VALUE;

    // See how tall everyone is. Also remember max width.
    for (int i = 0; i < count; ++i) {
        final View child = getVirtualChildAt(i);

        if (child == null) {
            mTotalLength += measureNullChild(i);
            continue;
        }

        if (child.getVisibility() == View.GONE) {
            i += getChildrenSkipCount(child, i);
            continue;
        }

        if (hasDividerBeforeChildAt(i)) {
            mTotalLength += mDividerHeight;
        }

        LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child.getLayoutParams();

        totalWeight += lp.weight;

        if (heightMode == MeasureSpec.EXACTLY && lp.height == 0 && lp.weight > 0) {
            // Optimization: don't bother measuring children who are going to use
            // leftover space. These views will get measured again down below if
            // there is any leftover space.
            final int totalLength = mTotalLength;
            mTotalLength = Math.max(totalLength, totalLength + lp.topMargin + lp.bottomMargin);
            skippedMeasure = true;
        } else {
            int oldHeight = Integer.MIN_VALUE;

            if (lp.height == 0 && lp.weight > 0) {
                // heightMode is either UNSPECIFIED or AT_MOST, and this
                // child wanted to stretch to fill available space.
                // Translate that to WRAP_CONTENT so that it does not end up
                // with a height of 0
                oldHeight = 0;
                lp.height = LayoutParams.WRAP_CONTENT;
            }

            // Determine how big this child would like to be. If this or
            // previous children have given a weight, then we allow it to
            // use all available space (and we will shrink things later
            // if needed).
            measureChildBeforeLayout(child, i, widthMeasureSpec, 0, heightMeasureSpec,
                    totalWeight == 0 ? mTotalLength : 0);

            if (oldHeight != Integer.MIN_VALUE) {
                lp.height = oldHeight;
            }

            final int childHeight = child.getMeasuredHeight();
            final int totalLength = mTotalLength;
            mTotalLength = Math.max(totalLength,
                    totalLength + childHeight + lp.topMargin + lp.bottomMargin + getNextLocationOffset(child));

            if (useLargestChild) {
                largestChildHeight = Math.max(childHeight, largestChildHeight);
            }
        }

        /**
         * If applicable, compute the additional offset to the child's baseline
         * we'll need later when asked {@link #getBaseline}.
         */
        if ((baselineChildIndex >= 0) && (baselineChildIndex == i + 1)) {
            mBaselineChildTop = mTotalLength;
        }

        // if we are trying to use a child index for our baseline, the above
        // book keeping only works if there are no children above it with
        // weight.  fail fast to aid the developer.
        if (i < baselineChildIndex && lp.weight > 0) {
            throw new RuntimeException("A child of LinearLayout with index "
                    + "less than mBaselineAlignedChildIndex has weight > 0, which "
                    + "won't work.  Either remove the weight, or don't set " + "mBaselineAlignedChildIndex.");
        }

        boolean matchWidthLocally = false;
        if (widthMode != MeasureSpec.EXACTLY && lp.width == LayoutParams.MATCH_PARENT) {
            // The width of the linear layout will scale, and at least one
            // child said it wanted to match our width. Set a flag
            // indicating that we need to remeasure at least that view when
            // we know our width.
            matchWidth = true;
            matchWidthLocally = true;
        }

        final int margin = lp.leftMargin + lp.rightMargin;
        final int measuredWidth = child.getMeasuredWidth() + margin;
        maxWidth = Math.max(maxWidth, measuredWidth);
        childState = ViewUtils.combineMeasuredStates(childState, ViewCompat.getMeasuredState(child));

        allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT;
        if (lp.weight > 0) {
            /*
             * Widths of weighted Views are bogus if we end up
             * remeasuring, so keep them separate.
             */
            weightedMaxWidth = Math.max(weightedMaxWidth, matchWidthLocally ? margin : measuredWidth);
        } else {
            alternativeMaxWidth = Math.max(alternativeMaxWidth, matchWidthLocally ? margin : measuredWidth);
        }

        i += getChildrenSkipCount(child, i);
    }

    if (mTotalLength > 0 && hasDividerBeforeChildAt(count)) {
        mTotalLength += mDividerHeight;
    }

    if (useLargestChild && (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED)) {
        mTotalLength = 0;

        for (int i = 0; i < count; ++i) {
            final View child = getVirtualChildAt(i);

            if (child == null) {
                mTotalLength += measureNullChild(i);
                continue;
            }

            if (child.getVisibility() == GONE) {
                i += getChildrenSkipCount(child, i);
                continue;
            }

            final LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child
                    .getLayoutParams();
            // Account for negative margins
            final int totalLength = mTotalLength;
            mTotalLength = Math.max(totalLength, totalLength + largestChildHeight + lp.topMargin
                    + lp.bottomMargin + getNextLocationOffset(child));
        }
    }

    // Add in our padding
    mTotalLength += getPaddingTop() + getPaddingBottom();

    int heightSize = mTotalLength;

    // Check against our minimum height
    heightSize = Math.max(heightSize, getSuggestedMinimumHeight());

    // Reconcile our calculated size with the heightMeasureSpec
    int heightSizeAndState = ViewCompat.resolveSizeAndState(heightSize, heightMeasureSpec, 0);
    heightSize = heightSizeAndState & ViewCompat.MEASURED_SIZE_MASK;

    // Either expand children with weight to take up available space or
    // shrink them if they extend beyond our current bounds. If we skipped
    // measurement on any children, we need to measure them now.
    int delta = heightSize - mTotalLength;
    if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
        float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;

        mTotalLength = 0;

        for (int i = 0; i < count; ++i) {
            final View child = getVirtualChildAt(i);

            if (child.getVisibility() == View.GONE) {
                continue;
            }

            LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child.getLayoutParams();

            float childExtra = lp.weight;
            if (childExtra > 0) {
                // Child said it could absorb extra space -- give him his share
                int share = (int) (childExtra * delta / weightSum);
                weightSum -= childExtra;
                delta -= share;

                final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
                        getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin, lp.width);

                // TODO: Use a field like lp.isMeasured to figure out if this
                // child has been previously measured
                if ((lp.height != 0) || (heightMode != MeasureSpec.EXACTLY)) {
                    // child was measured once already above...
                    // base new measurement on stored values
                    int childHeight = child.getMeasuredHeight() + share;
                    if (childHeight < 0) {
                        childHeight = 0;
                    }

                    child.measure(childWidthMeasureSpec,
                            MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
                } else {
                    // child was skipped in the loop above.
                    // Measure for this first time here
                    child.measure(childWidthMeasureSpec,
                            MeasureSpec.makeMeasureSpec(share > 0 ? share : 0, MeasureSpec.EXACTLY));
                }

                // Child may now not fit in vertical dimension.
                childState = ViewUtils.combineMeasuredStates(childState, ViewCompat.getMeasuredState(child)
                        & (ViewCompat.MEASURED_STATE_MASK >> ViewCompat.MEASURED_HEIGHT_STATE_SHIFT));
            }

            final int margin = lp.leftMargin + lp.rightMargin;
            final int measuredWidth = child.getMeasuredWidth() + margin;
            maxWidth = Math.max(maxWidth, measuredWidth);

            boolean matchWidthLocally = widthMode != MeasureSpec.EXACTLY
                    && lp.width == LayoutParams.MATCH_PARENT;

            alternativeMaxWidth = Math.max(alternativeMaxWidth, matchWidthLocally ? margin : measuredWidth);

            allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT;

            final int totalLength = mTotalLength;
            mTotalLength = Math.max(totalLength, totalLength + child.getMeasuredHeight() + lp.topMargin
                    + lp.bottomMargin + getNextLocationOffset(child));
        }

        // Add in our padding
        mTotalLength += getPaddingTop() + getPaddingBottom();
        // TODO: Should we recompute the heightSpec based on the new total length?
    } else {
        alternativeMaxWidth = Math.max(alternativeMaxWidth, weightedMaxWidth);

        // We have no limit, so make all weighted views as tall as the largest child.
        // Children will have already been measured once.
        if (useLargestChild && heightMode != MeasureSpec.EXACTLY) {
            for (int i = 0; i < count; i++) {
                final View child = getVirtualChildAt(i);

                if (child == null || child.getVisibility() == View.GONE) {
                    continue;
                }

                final LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child
                        .getLayoutParams();

                float childExtra = lp.weight;
                if (childExtra > 0) {
                    child.measure(MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), MeasureSpec.EXACTLY),
                            MeasureSpec.makeMeasureSpec(largestChildHeight, MeasureSpec.EXACTLY));
                }
            }
        }
    }

    if (!allFillParent && widthMode != MeasureSpec.EXACTLY) {
        maxWidth = alternativeMaxWidth;
    }

    maxWidth += getPaddingLeft() + getPaddingRight();

    // Check against our minimum width
    maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());

    setMeasuredDimension(ViewCompat.resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
            heightSizeAndState);

    if (matchWidth) {
        forceUniformWidth(count, heightMeasureSpec);
    }
}