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.actionbarsherlock.internal.widget.ActionBarView.java

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int childCount = getChildCount();
    if (mIsCollapsable) {
        int visibleChildren = 0;
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE && !(child == mMenuView && mMenuView.getChildCount() == 0)) {
                visibleChildren++;/* ww w .  ja  va 2s .co  m*/
            }
        }

        if (visibleChildren == 0) {
            // No size for an empty action bar when collapsable.
            setMeasuredDimension(0, 0);
            mIsCollapsed = true;
            return;
        }
    }
    mIsCollapsed = false;

    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    if (widthMode != MeasureSpec.EXACTLY) {
        throw new IllegalStateException(getClass().getSimpleName() + " can only be used "
                + "with android:layout_width=\"match_parent\" (or fill_parent)");
    }

    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    if (heightMode != MeasureSpec.AT_MOST) {
        throw new IllegalStateException(getClass().getSimpleName() + " can only be used "
                + "with android:layout_height=\"wrap_content\"");
    }

    int contentWidth = MeasureSpec.getSize(widthMeasureSpec);

    int maxHeight = mContentHeight > 0 ? mContentHeight : MeasureSpec.getSize(heightMeasureSpec);

    final int verticalPadding = getPaddingTop() + getPaddingBottom();
    final int paddingLeft = getPaddingLeft();
    final int paddingRight = getPaddingRight();
    final int height = maxHeight - verticalPadding;
    final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);

    int availableWidth = contentWidth - paddingLeft - paddingRight;
    int leftOfCenter = availableWidth / 2;
    int rightOfCenter = leftOfCenter;

    HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;

    if (homeLayout.getVisibility() != GONE) {
        final ViewGroup.LayoutParams lp = homeLayout.getLayoutParams();
        int homeWidthSpec;
        if (lp.width < 0) {
            homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
        } else {
            homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
        }
        homeLayout.measure(homeWidthSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
        final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getLeftOffset();
        availableWidth = Math.max(0, availableWidth - homeWidth);
        leftOfCenter = Math.max(0, availableWidth - homeWidth);
    }

    if (mMenuView != null && mMenuView.getParent() == this) {
        availableWidth = measureChildView(mMenuView, availableWidth, childSpecHeight, 0);
        rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth());
    }

    if (mIndeterminateProgressView != null && mIndeterminateProgressView.getVisibility() != GONE) {
        availableWidth = measureChildView(mIndeterminateProgressView, availableWidth, childSpecHeight, 0);
        rightOfCenter = Math.max(0, rightOfCenter - mIndeterminateProgressView.getMeasuredWidth());
    }

    final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE
            && (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;

    if (mExpandedActionView == null) {
        switch (mNavigationMode) {
        case ActionBar.NAVIGATION_MODE_LIST:
            if (mListNavLayout != null) {
                final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
                availableWidth = Math.max(0, availableWidth - itemPaddingSize);
                leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
                mListNavLayout.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
                        MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
                final int listNavWidth = mListNavLayout.getMeasuredWidth();
                availableWidth = Math.max(0, availableWidth - listNavWidth);
                leftOfCenter = Math.max(0, leftOfCenter - listNavWidth);
            }
            break;
        case ActionBar.NAVIGATION_MODE_TABS:
            if (mTabScrollView != null) {
                final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
                availableWidth = Math.max(0, availableWidth - itemPaddingSize);
                leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
                mTabScrollView.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
                        MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
                final int tabWidth = mTabScrollView.getMeasuredWidth();
                availableWidth = Math.max(0, availableWidth - tabWidth);
                leftOfCenter = Math.max(0, leftOfCenter - tabWidth);
            }
            break;
        }
    }

    View customView = null;
    if (mExpandedActionView != null) {
        customView = mExpandedActionView;
    } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
        customView = mCustomNavView;
    }

    if (customView != null) {
        final ViewGroup.LayoutParams lp = generateLayoutParams(customView.getLayoutParams());
        final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ? (ActionBar.LayoutParams) lp
                : null;

        int horizontalMargin = 0;
        int verticalMargin = 0;
        if (ablp != null) {
            horizontalMargin = ablp.leftMargin + ablp.rightMargin;
            verticalMargin = ablp.topMargin + ablp.bottomMargin;
        }

        // If the action bar is wrapping to its content height, don't allow a custom
        // view to MATCH_PARENT.
        int customNavHeightMode;
        if (mContentHeight <= 0) {
            customNavHeightMode = MeasureSpec.AT_MOST;
        } else {
            customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ? MeasureSpec.EXACTLY
                    : MeasureSpec.AT_MOST;
        }
        final int customNavHeight = Math.max(0,
                (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin);

        final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ? MeasureSpec.EXACTLY
                : MeasureSpec.AT_MOST;
        int customNavWidth = Math.max(0,
                (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth) - horizontalMargin);
        final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY)
                & Gravity.HORIZONTAL_GRAVITY_MASK;

        // Centering a custom view is treated specially; we try to center within the whole
        // action bar rather than in the available space.
        if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.MATCH_PARENT) {
            customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2;
        }

        customView.measure(MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
                MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
        availableWidth -= horizontalMargin + customView.getMeasuredWidth();
    }

    if (mExpandedActionView == null && showTitle) {
        availableWidth = measureChildView(mTitleLayout, availableWidth,
                MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
        leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
    }

    if (mContentHeight <= 0) {
        int measuredHeight = 0;
        for (int i = 0; i < childCount; i++) {
            View v = getChildAt(i);
            int paddedViewHeight = v.getMeasuredHeight() + verticalPadding;
            if (paddedViewHeight > measuredHeight) {
                measuredHeight = paddedViewHeight;
            }
        }
        setMeasuredDimension(contentWidth, measuredHeight);
    } else {
        setMeasuredDimension(contentWidth, maxHeight);
    }

    if (mContextView != null) {
        mContextView.setContentHeight(getMeasuredHeight());
    }

    if (mProgressView != null && mProgressView.getVisibility() != GONE) {
        mProgressView.measure(
                MeasureSpec.makeMeasureSpec(contentWidth - mProgressBarPadding * 2, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST));
    }
}

From source file:com.devabit.takestock.ui.widget.FlexboxLayout.java

/**
 * Sub method for {@link #onMeasure(int, int)}, when the main axis direction is horizontal
 * (either left to right or right to left).
 *
 * @param widthMeasureSpec  horizontal space requirements as imposed by the parent
 * @param heightMeasureSpec vertical space requirements as imposed by the parent
 * @see #onMeasure(int, int)/*from  ww w. j  ava  2 s  . c  o m*/
 * @see #setFlexDirection(int)
 * @see #setFlexWrap(int)
 * @see #setAlignItems(int)
 * @see #setAlignContent(int)
 */
private void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int childState = 0;

    mFlexLines.clear();

    // Determine how many flex lines are needed in this layout by measuring each child.
    // (Expand or shrink the view depending on the flexGrow and flexShrink attributes in a later
    // loop)
    {
        int childCount = getChildCount();
        int paddingStart = ViewCompat.getPaddingStart(this);
        int paddingEnd = ViewCompat.getPaddingEnd(this);
        int largestHeightInRow = Integer.MIN_VALUE;
        FlexLine flexLine = new FlexLine();
        flexLine.mainSize = paddingStart + paddingEnd;
        for (int i = 0; i < childCount; i++) {
            View child = getReorderedChildAt(i);
            if (child == null) {
                addFlexLineIfLastFlexItem(i, childCount, flexLine);
                continue;
            } else if (child.getVisibility() == View.GONE) {
                flexLine.itemCount++;
                addFlexLineIfLastFlexItem(i, childCount, flexLine);
                continue;
            }

            FlexboxLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (lp.alignSelf == LayoutParams.ALIGN_SELF_STRETCH) {
                flexLine.indicesAlignSelfStretch.add(i);
            }

            int childWidth = lp.width;
            if (lp.flexBasisPercent != LayoutParams.FLEX_BASIS_PERCENT_DEFAULT
                    && widthMode == MeasureSpec.EXACTLY) {
                childWidth = Math.round(widthSize * lp.flexBasisPercent);
                // Use the dimension from the layout_width attribute if the widthMode is not
                // MeasureSpec.EXACTLY even if any fraction value is set to
                // layout_flexBasisPercent.
                // There are likely quite few use cases where assigning any fraction values
                // with widthMode is not MeasureSpec.EXACTLY (e.g. FlexboxLayout's layout_width
                // is set to wrap_content)
            }
            int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
                    getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin, childWidth);
            int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
                    getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin, lp.height);
            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

            // Check the size constraint after the first measurement for the child
            // To prevent the child's width/height violate the size constraints imposed by the
            // {@link LayoutParams#minWidth}, {@link LayoutParams#minHeight},
            // {@link LayoutParams#maxWidth} and {@link LayoutParams#maxHeight} attributes.
            // E.g. When the child's layout_width is wrap_content the measured width may be
            // less than the min width after the first measurement.
            checkSizeConstraints(child);

            childState = ViewCompat.combineMeasuredStates(childState, ViewCompat.getMeasuredState(child));
            largestHeightInRow = Math.max(largestHeightInRow,
                    child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);

            if (isWrapRequired(mFlexWrap, widthMode, widthSize, flexLine.mainSize,
                    child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin, lp)) {
                if (flexLine.itemCount > 0) {
                    mFlexLines.add(flexLine);
                }

                flexLine = new FlexLine();
                flexLine.itemCount = 1;
                flexLine.mainSize = paddingStart + paddingEnd;
                largestHeightInRow = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
            } else {
                flexLine.itemCount++;
            }
            flexLine.mainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            flexLine.totalFlexGrow += lp.flexGrow;
            flexLine.totalFlexShrink += lp.flexShrink;
            // Temporarily set the cross axis length as the largest child in the row
            // Expand along the cross axis depending on the mAlignContent property if needed
            // later
            flexLine.crossSize = Math.max(flexLine.crossSize, largestHeightInRow);

            if (mFlexWrap != FLEX_WRAP_WRAP_REVERSE) {
                flexLine.maxBaseline = Math.max(flexLine.maxBaseline, child.getBaseline() + lp.topMargin);
            } else {
                // if the flex wrap property is FLEX_WRAP_WRAP_REVERSE, calculate the
                // baseline as the distance from the cross end and the baseline
                // since the cross size calculation is based on the distance from the cross end
                flexLine.maxBaseline = Math.max(flexLine.maxBaseline,
                        child.getMeasuredHeight() - child.getBaseline() + lp.bottomMargin);
            }
            addFlexLineIfLastFlexItem(i, childCount, flexLine);
        }
    }

    determineMainSize(mFlexDirection, widthMeasureSpec, heightMeasureSpec);

    // TODO: Consider the case any individual child's alignSelf is set to ALIGN_SELF_BASELINE
    if (mAlignItems == ALIGN_ITEMS_BASELINE) {
        int viewIndex = 0;
        for (FlexLine flexLine : mFlexLines) {
            // The largest height value that also take the baseline shift into account
            int largestHeightInLine = Integer.MIN_VALUE;
            for (int i = viewIndex; i < viewIndex + flexLine.itemCount; i++) {
                View child = getReorderedChildAt(i);
                LayoutParams lp = (LayoutParams) child.getLayoutParams();
                if (mFlexWrap != FLEX_WRAP_WRAP_REVERSE) {
                    int marginTop = flexLine.maxBaseline - child.getBaseline();
                    marginTop = Math.max(marginTop, lp.topMargin);
                    largestHeightInLine = Math.max(largestHeightInLine,
                            child.getHeight() + marginTop + lp.bottomMargin);
                } else {
                    int marginBottom = flexLine.maxBaseline - child.getMeasuredHeight() + child.getBaseline();
                    marginBottom = Math.max(marginBottom, lp.bottomMargin);
                    largestHeightInLine = Math.max(largestHeightInLine,
                            child.getHeight() + lp.topMargin + marginBottom);
                }
            }
            flexLine.crossSize = largestHeightInLine;
            viewIndex += flexLine.itemCount;
        }
    }

    determineCrossSize(mFlexDirection, widthMeasureSpec, heightMeasureSpec,
            getPaddingTop() + getPaddingBottom());
    // Now cross size for each flex line is determined.
    // Expand the views if alignItems (or alignSelf in each child view) is set to stretch
    stretchViews(mFlexDirection, mAlignItems);
    setMeasuredDimensionForFlex(mFlexDirection, widthMeasureSpec, heightMeasureSpec, childState);
}

From source file:android.support.v17.leanback.widget.GridLayoutManager.java

private void measureScrapChild(int position, int widthSpec, int heightSpec, int[] measuredDimension) {
    View view = mRecycler.getViewForPosition(position);
    if (view != null) {
        final LayoutParams p = (LayoutParams) view.getLayoutParams();
        calculateItemDecorationsForChild(view, sTempRect);
        int widthUsed = p.leftMargin + p.rightMargin + sTempRect.left + sTempRect.right;
        int heightUsed = p.topMargin + p.bottomMargin + sTempRect.top + sTempRect.bottom;

        int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                getPaddingLeft() + getPaddingRight() + widthUsed, p.width);
        int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                getPaddingTop() + getPaddingBottom() + heightUsed, p.height);
        view.measure(childWidthSpec, childHeightSpec);

        measuredDimension[0] = getDecoratedMeasuredWidthWithMargin(view);
        measuredDimension[1] = getDecoratedMeasuredHeightWithMargin(view);
        mRecycler.recycleView(view);/*from ww  w.j  ava  2  s .  c  o  m*/
    }
}

From source file:com.google.android.flexbox.FlexboxLayoutManager.java

private int layoutFlexLineMainAxisHorizontal(FlexLine flexLine, LayoutState layoutState) {
    assert mFlexboxHelper.mMeasureSpecCache != null;

    int paddingLeft = getPaddingLeft();
    int paddingRight = getPaddingRight();
    int parentWidth = getWidth();

    int childTop = layoutState.mOffset;
    if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) {
        childTop = childTop - flexLine.mCrossSize;
    }/*w  w w  . ja  v a  2  s  .co  m*/
    int startPosition = layoutState.mPosition;

    float childLeft;

    // Only used when mIsRtl is true
    float childRight;
    float spaceBetweenItem = 0f;
    switch (mJustifyContent) {
    case JustifyContent.FLEX_START:
        childLeft = paddingLeft;
        childRight = parentWidth - paddingRight;
        break;
    case JustifyContent.FLEX_END:
        childLeft = parentWidth - flexLine.mMainSize + paddingRight;
        childRight = flexLine.mMainSize - paddingLeft;
        break;
    case JustifyContent.CENTER:
        childLeft = paddingLeft + (parentWidth - flexLine.mMainSize) / 2f;
        childRight = parentWidth - paddingRight - (parentWidth - flexLine.mMainSize) / 2f;
        break;
    case JustifyContent.SPACE_AROUND:
        if (flexLine.mItemCount != 0) {
            spaceBetweenItem = (parentWidth - flexLine.mMainSize) / (float) flexLine.mItemCount;
        }
        childLeft = paddingLeft + spaceBetweenItem / 2f;
        childRight = parentWidth - paddingRight - spaceBetweenItem / 2f;
        break;
    case JustifyContent.SPACE_BETWEEN:
        childLeft = paddingLeft;
        float denominator = flexLine.mItemCount != 1 ? flexLine.mItemCount - 1 : 1f;
        spaceBetweenItem = (parentWidth - flexLine.mMainSize) / denominator;
        childRight = parentWidth - paddingRight;
        break;
    case JustifyContent.SPACE_EVENLY:
        if (flexLine.mItemCount != 0) {
            spaceBetweenItem = (parentWidth - flexLine.mMainSize) / (float) (flexLine.mItemCount + 1);
        }
        childLeft = paddingLeft + spaceBetweenItem;
        childRight = parentWidth - paddingRight - spaceBetweenItem;
        break;
    default:
        throw new IllegalStateException("Invalid justifyContent is set: " + mJustifyContent);
    }
    childLeft -= mAnchorInfo.mPerpendicularCoordinate;
    childRight -= mAnchorInfo.mPerpendicularCoordinate;
    spaceBetweenItem = Math.max(spaceBetweenItem, 0);

    // Used only when mLayoutDirection == LayoutState.LAYOUT_START to remember the index
    // a flex item should be inserted
    int indexInFlexLine = 0;
    for (int i = startPosition, itemCount = flexLine.getItemCount(); i < startPosition + itemCount; i++) {
        View view = getFlexItemAt(i);
        if (view == null) {
            continue;
        }

        if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) {
            calculateItemDecorationsForChild(view, TEMP_RECT);
            addView(view);
        } else {
            calculateItemDecorationsForChild(view, TEMP_RECT);
            addView(view, indexInFlexLine);
            indexInFlexLine++;
        }

        // Retrieve the measure spec from the cache because the view may be re-created when
        // retrieved from Recycler, in that case measured width/height are set to 0 even
        // each visible child should be measured at least once in the FlexboxHelper
        long measureSpec = mFlexboxHelper.mMeasureSpecCache[i];
        int widthSpec = mFlexboxHelper.extractLowerInt(measureSpec);
        int heightSpec = mFlexboxHelper.extractHigherInt(measureSpec);
        LayoutParams lp = (LayoutParams) view.getLayoutParams();
        if (shouldMeasureChild(view, widthSpec, heightSpec, lp)) {
            view.measure(widthSpec, heightSpec);
        }

        childLeft += (lp.leftMargin + getLeftDecorationWidth(view));
        childRight -= (lp.rightMargin + getRightDecorationWidth(view));

        int topWithDecoration = childTop + getTopDecorationHeight(view);
        if (mIsRtl) {
            mFlexboxHelper.layoutSingleChildHorizontal(view, flexLine,
                    Math.round(childRight) - view.getMeasuredWidth(), topWithDecoration, Math.round(childRight),
                    topWithDecoration + view.getMeasuredHeight());
        } else {
            mFlexboxHelper.layoutSingleChildHorizontal(view, flexLine, Math.round(childLeft), topWithDecoration,
                    Math.round(childLeft) + view.getMeasuredWidth(),
                    topWithDecoration + view.getMeasuredHeight());
        }
        childLeft += (view.getMeasuredWidth() + lp.rightMargin + getRightDecorationWidth(view)
                + spaceBetweenItem);
        childRight -= (view.getMeasuredWidth() + lp.leftMargin + getLeftDecorationWidth(view)
                + spaceBetweenItem);
    }
    layoutState.mFlexLinePosition += mLayoutState.mLayoutDirection;
    return flexLine.getCrossSize();
}

From source file:com.devabit.takestock.ui.widget.FlexboxLayout.java

/**
 * Shrink the flex items along the main axis based on the individual flexShrink attribute.
 *
 * @param flexLine             the flex line to which flex items belong
 * @param flexDirection        the flexDirection value for this FlexboxLayout
 * @param maxMainSize          the maximum main size. Shrank main size will be this size
 * @param paddingAlongMainAxis the padding value along the main axis
 * @param startIndex           the start index of the children views to be shrank. This index
 *                             needs to/*from  w  w w. ja va2 s .co  m*/
 *                             be an absolute index in the flex container (FlexboxLayout),
 *                             not the relative index in the flex line.
 * @return the next index, the next flex line's first flex item starts from the returned index
 * @see #getFlexDirection()
 * @see #setFlexDirection(int)
 * @see LayoutParams#flexShrink
 */
private int shrinkFlexItems(FlexLine flexLine, @FlexDirection int flexDirection, int maxMainSize,
        int paddingAlongMainAxis, int startIndex) {
    int childIndex = startIndex;
    int sizeBeforeShrink = flexLine.mainSize;
    if (flexLine.totalFlexShrink <= 0 || maxMainSize > flexLine.mainSize) {
        childIndex += flexLine.itemCount;
        return childIndex;
    }
    boolean needsReshrink = false;
    float unitShrink = (flexLine.mainSize - maxMainSize) / flexLine.totalFlexShrink;
    float accumulatedRoundError = 0;
    flexLine.mainSize = paddingAlongMainAxis;
    for (int i = 0; i < flexLine.itemCount; i++) {
        View child = getReorderedChildAt(childIndex);
        if (child == null) {
            continue;
        } else if (child.getVisibility() == View.GONE) {
            childIndex++;
            continue;
        }
        LayoutParams lp = (LayoutParams) child.getLayoutParams();
        if (flexDirection == FLEX_DIRECTION_ROW || flexDirection == FLEX_DIRECTION_ROW_REVERSE) {
            // The direction of main axis is horizontal
            if (!mChildrenFrozen[childIndex]) {
                float rawCalculatedWidth = child.getMeasuredWidth() - unitShrink * lp.flexShrink;
                if (i == flexLine.itemCount - 1) {
                    rawCalculatedWidth += accumulatedRoundError;
                    accumulatedRoundError = 0;
                }
                int newWidth = Math.round(rawCalculatedWidth);
                if (newWidth < lp.minWidth) {
                    // This means the child doesn't have enough space to distribute the negative
                    // free space. To adjust the flex line length down to the maxMainSize, remaining
                    // negative free space needs to be re-distributed to other flex items
                    // (children views). In that case, invoke this method again with the same
                    // startIndex.
                    needsReshrink = true;
                    newWidth = lp.minWidth;
                    mChildrenFrozen[childIndex] = true;
                    flexLine.totalFlexShrink -= lp.flexShrink;
                } else {
                    accumulatedRoundError += (rawCalculatedWidth - newWidth);
                    if (accumulatedRoundError > 1.0) {
                        newWidth += 1;
                        accumulatedRoundError -= 1;
                    } else if (accumulatedRoundError < -1.0) {
                        newWidth -= 1;
                        accumulatedRoundError += 1;
                    }
                }
                child.measure(MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY));
            }
            flexLine.mainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
        } else {
            // The direction of main axis is vertical
            if (!mChildrenFrozen[childIndex]) {
                float rawCalculatedHeight = child.getMeasuredHeight() - unitShrink * lp.flexShrink;
                if (i == flexLine.itemCount - 1) {
                    rawCalculatedHeight += accumulatedRoundError;
                    accumulatedRoundError = 0;
                }
                int newHeight = Math.round(rawCalculatedHeight);
                if (newHeight < lp.minHeight) {
                    // Need to invoke this method again like the case flex direction is vertical
                    needsReshrink = true;
                    newHeight = lp.minHeight;
                    mChildrenFrozen[childIndex] = true;
                    flexLine.totalFlexShrink -= lp.flexShrink;
                } else {
                    accumulatedRoundError += (rawCalculatedHeight - newHeight);
                    if (accumulatedRoundError > 1.0) {
                        newHeight += 1;
                        accumulatedRoundError -= 1;
                    } else if (accumulatedRoundError < -1.0) {
                        newHeight -= 1;
                        accumulatedRoundError += 1;
                    }
                }
                child.measure(MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY));
            }
            flexLine.mainSize += child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
        }
        childIndex++;
    }

    if (needsReshrink && sizeBeforeShrink != flexLine.mainSize) {
        // Re-invoke the method with the same startIndex to distribute the negative free space
        // that wasn't fully distributed (because some views length were not enough)
        shrinkFlexItems(flexLine, flexDirection, maxMainSize, paddingAlongMainAxis, startIndex);
    }
    return childIndex;
}

From source file:com.devabit.takestock.ui.widget.FlexboxLayout.java

/**
 * Expand the flex items along the main axis based on the individual flexGrow attribute.
 *
 * @param flexLine             the flex line to which flex items belong
 * @param flexDirection        the flexDirection value for this FlexboxLayout
 * @param maxMainSize          the maximum main size. Expanded main size will be this size
 * @param paddingAlongMainAxis the padding value along the main axis
 * @param startIndex           the start index of the children views to be expanded. This index
 *                             needs to// w ww .  j  ava 2  s.co m
 *                             be an absolute index in the flex container (FlexboxLayout),
 *                             not the relative index in the flex line.
 * @return the next index, the next flex line's first flex item starts from the returned index
 * @see #getFlexDirection()
 * @see #setFlexDirection(int)
 * @see LayoutParams#flexGrow
 */
private int expandFlexItems(FlexLine flexLine, @FlexDirection int flexDirection, int maxMainSize,
        int paddingAlongMainAxis, int startIndex) {
    int childIndex = startIndex;
    if (flexLine.totalFlexGrow <= 0 || maxMainSize < flexLine.mainSize) {
        childIndex += flexLine.itemCount;
        return childIndex;
    }
    int sizeBeforeExpand = flexLine.mainSize;
    boolean needsReexpand = false;
    float unitSpace = (maxMainSize - flexLine.mainSize) / flexLine.totalFlexGrow;
    flexLine.mainSize = paddingAlongMainAxis;
    float accumulatedRoundError = 0;
    for (int i = 0; i < flexLine.itemCount; i++) {
        View child = getReorderedChildAt(childIndex);
        if (child == null) {
            continue;
        } else if (child.getVisibility() == View.GONE) {
            childIndex++;
            continue;
        }
        LayoutParams lp = (LayoutParams) child.getLayoutParams();
        if (flexDirection == FLEX_DIRECTION_ROW || flexDirection == FLEX_DIRECTION_ROW_REVERSE) {
            // The direction of the main axis is horizontal
            if (!mChildrenFrozen[childIndex]) {
                float rawCalculatedWidth = child.getMeasuredWidth() + unitSpace * lp.flexGrow;
                if (i == flexLine.itemCount - 1) {
                    rawCalculatedWidth += accumulatedRoundError;
                    accumulatedRoundError = 0;
                }
                int newWidth = Math.round(rawCalculatedWidth);
                if (newWidth > lp.maxWidth) {
                    // This means the child can't expand beyond the value of the maxWidth attribute.
                    // To adjust the flex line length to the size of maxMainSize, remaining
                    // positive free space needs to be re-distributed to other flex items
                    // (children views). In that case, invoke this method again with the same
                    // startIndex.
                    needsReexpand = true;
                    newWidth = lp.maxWidth;
                    mChildrenFrozen[childIndex] = true;
                    flexLine.totalFlexGrow -= lp.flexGrow;
                } else {
                    accumulatedRoundError += (rawCalculatedWidth - newWidth);
                    if (accumulatedRoundError > 1.0) {
                        newWidth += 1;
                        accumulatedRoundError -= 1.0;
                    } else if (accumulatedRoundError < -1.0) {
                        newWidth -= 1;
                        accumulatedRoundError += 1.0;
                    }
                }
                child.measure(MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY));
            }
            flexLine.mainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
        } else {
            // The direction of the main axis is vertical
            if (!mChildrenFrozen[childIndex]) {
                float rawCalculatedHeight = child.getMeasuredHeight() + unitSpace * lp.flexGrow;
                if (i == flexLine.itemCount - 1) {
                    rawCalculatedHeight += accumulatedRoundError;
                    accumulatedRoundError = 0;
                }
                int newHeight = Math.round(rawCalculatedHeight);
                if (newHeight > lp.maxHeight) {
                    // This means the child can't expand beyond the value of the maxHeight
                    // attribute.
                    // To adjust the flex line length to the size of maxMainSize, remaining
                    // positive free space needs to be re-distributed to other flex items
                    // (children views). In that case, invoke this method again with the same
                    // startIndex.
                    needsReexpand = true;
                    newHeight = lp.maxHeight;
                    mChildrenFrozen[childIndex] = true;
                    flexLine.totalFlexGrow -= lp.flexGrow;
                } else {
                    accumulatedRoundError += (rawCalculatedHeight - newHeight);
                    if (accumulatedRoundError > 1.0) {
                        newHeight += 1;
                        accumulatedRoundError -= 1.0;
                    } else if (accumulatedRoundError < -1.0) {
                        newHeight -= 1;
                        accumulatedRoundError += 1.0;
                    }
                }
                child.measure(MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY));
            }
            flexLine.mainSize += child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
        }
        childIndex++;
    }

    if (needsReexpand && sizeBeforeExpand != flexLine.mainSize) {
        // Re-invoke the method with the same startIndex to distribute the positive free space
        // that wasn't fully distributed (because of maximum length constraint)
        expandFlexItems(flexLine, flexDirection, maxMainSize, paddingAlongMainAxis, startIndex);
    }
    return childIndex;
}

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

/**
 * <p>Builds the popup window's content and returns the height the popup
 * should have. Returns -1 when the content already exists.</p>
 *
 * @return the content's height or -1 if content already exists
 *//*from  ww w.j  av  a  2  s.  com*/
private int buildDropDown() {
    ViewGroup dropDownView;
    int otherHeights = 0;

    if (mDropDownList == null) {
        Context context = mContext;

        /**
         * This Runnable exists for the sole purpose of checking if the view layout has got
         * completed and if so call showDropDown to display the drop down. This is used to show
         * the drop down as soon as possible after user opens up the search dialog, without
         * waiting for the normal UI pipeline to do it's job which is slower than this method.
         */
        mShowDropDownRunnable = new Runnable() {
            public void run() {
                // View layout should be all done before displaying the drop down.
                View view = getAnchorView();
                if (view != null && view.getWindowToken() != null) {
                    show();
                }
            }
        };

        mDropDownList = createDropDownListView(context, !mModal);
        if (mDropDownListHighlight != null) {
            mDropDownList.setSelector(mDropDownListHighlight);
        }
        mDropDownList.setAdapter(mAdapter);
        mDropDownList.setOnItemClickListener(mItemClickListener);
        mDropDownList.setFocusable(true);
        mDropDownList.setFocusableInTouchMode(true);
        mDropDownList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                if (position != -1) {
                    XpDropDownListView dropDownList = mDropDownList;

                    if (dropDownList != null) {
                        dropDownList.setListSelectionHidden(false);
                    }
                }
            }

            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
        mDropDownList.setOnScrollListener(mScrollListener);

        if (mItemSelectedListener != null) {
            mDropDownList.setOnItemSelectedListener(mItemSelectedListener);
        }

        dropDownView = mDropDownList;

        View hintView = mPromptView;
        if (hintView != null) {
            // if a hint has been specified, we accomodate more space for it and
            // add a text view in the drop down menu, at the bottom of the list
            LinearLayout hintContainer = new LinearLayout(context);
            hintContainer.setOrientation(LinearLayout.VERTICAL);

            LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, 0, 1.0f);

            switch (mPromptPosition) {
            case POSITION_PROMPT_BELOW:
                hintContainer.addView(dropDownView, hintParams);
                hintContainer.addView(hintView);
                break;

            case POSITION_PROMPT_ABOVE:
                hintContainer.addView(hintView);
                hintContainer.addView(dropDownView, hintParams);
                break;

            default:
                Log.e(TAG, "Invalid hint position " + mPromptPosition);
                break;
            }

            // Measure the hint's height to find how much more vertical
            // space we need to add to the drop down's height.
            final int widthSize;
            final int widthMode;
            if (mDropDownWidth >= 0) {
                widthMode = MeasureSpec.AT_MOST;
                widthSize = mDropDownWidth > mDropDownMaxWidth ? mDropDownMaxWidth : mDropDownWidth;
                //                    widthSize = mDropDownWidth;
            } else {
                if (mDropDownMaxWidth >= 0) {
                    widthMode = MeasureSpec.AT_MOST;
                    widthSize = mDropDownMaxWidth;
                } else {
                    widthMode = MeasureSpec.UNSPECIFIED;
                    widthSize = 0;
                }
            }
            //noinspection Range
            final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
            final int heightSpec = MeasureSpec.UNSPECIFIED;
            hintView.measure(widthSpec, heightSpec);

            hintParams = (LinearLayout.LayoutParams) hintView.getLayoutParams();
            otherHeights = hintView.getMeasuredHeight() + hintParams.topMargin + hintParams.bottomMargin;

            dropDownView = hintContainer;
        }

        mPopup.setContentView(dropDownView);
    } else {
        dropDownView = (ViewGroup) mPopup.getContentView();
        final View view = mPromptView;
        if (view != null) {
            LinearLayout.LayoutParams hintParams = (LinearLayout.LayoutParams) view.getLayoutParams();
            otherHeights = view.getMeasuredHeight() + hintParams.topMargin + hintParams.bottomMargin;
        }
    }

    // getMaxAvailableHeight() subtracts the padding, so we put it back
    // to get the available height for the whole window
    int padding = 0;
    Drawable background = mPopup.getBackground();
    if (background != null) {
        background.getPadding(mTempRect);
        padding = mTempRect.top + mTempRect.bottom;

        // If we don't have an explicit vertical offset, determine one from the window
        // background so that content will line up.
        //            if (!mDropDownVerticalOffsetSet) {
        //                mDropDownVerticalOffset = -mTempRect.top;
        //            }
    } else {
        mTempRect.setEmpty();
    }

    final int verticalMargin = mMargins.top + mMargins.bottom;

    // Max height available on the screen for a popup.
    final boolean ignoreBottomDecorations = mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
    //        final int maxHeight = getMaxAvailableHeight(getAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations);
    final int maxHeight = getMaxAvailableHeight(getAnchorView(), ignoreBottomDecorations);
    if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
        return maxHeight - verticalMargin + padding;
    }

    final int childWidthSpec;
    switch (mDropDownWidth) {
    case ViewGroup.LayoutParams.WRAP_CONTENT:
        childWidthSpec = MeasureSpec.makeMeasureSpec(getAnchorView().getWidth()
                - (mMargins.left + mMargins.right) - (mTempRect.left + mTempRect.right), MeasureSpec.AT_MOST);
        break;
    case ViewGroup.LayoutParams.MATCH_PARENT:
        childWidthSpec = MeasureSpec.makeMeasureSpec(mContext.getResources().getDisplayMetrics().widthPixels
                - (mMargins.left + mMargins.right) - (mTempRect.left + mTempRect.right), MeasureSpec.EXACTLY);
        break;
    case PREFERRED:
        int widthSize;
        int widthMode;
        if (mDropDownMaxWidth >= 0) {
            widthSize = mDropDownMaxWidth - (mMargins.left + mMargins.right)
                    - (mTempRect.left + mTempRect.right);
            widthMode = MeasureSpec.AT_MOST;
            childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
        } else {
            widthMode = MeasureSpec.AT_MOST;
            if (mDropDownMaxWidth == WRAP_CONTENT) {
                widthSize = getAnchorView().getWidth() - (mMargins.left + mMargins.right)
                        - (mTempRect.left + mTempRect.right);
            } else { // MATCH_PARENT
                widthSize = mContext.getResources().getDisplayMetrics().widthPixels
                        - (mMargins.left + mMargins.right) - (mTempRect.left + mTempRect.right);
            }
            childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
        }
        break;
    default:
        //noinspection Range
        childWidthSpec = MeasureSpec.makeMeasureSpec(mDropDownWidth, MeasureSpec.EXACTLY);
        break;
    }

    final int listPadding = mDropDownList.getPaddingTop() + mDropDownList.getPaddingBottom();
    final int listContent = mDropDownList.measureHeightOfChildrenCompat(childWidthSpec, 0,
            XpDropDownListView.NO_POSITION, maxHeight - otherHeights - verticalMargin - listPadding + padding,
            -1);
    // add padding only if the list has items in it, that way we don't show
    // the popup if it is not needed
    if (otherHeights > 0 || listContent > 0)
        otherHeights += padding + listPadding;

    return listContent + otherHeights;
}

From source file:com.example.uidemo.widget.waterfall.StaggeredGridView.java

/**
 * Measure and layout all currently visible children.
 *
 * @param queryAdapter true to requery the adapter for view data
 */// ww  w  .  ja va 2s  . c  om
final void layoutChildren(boolean queryAdapter) {
    final int paddingLeft = getPaddingLeft();
    final int paddingRight = getPaddingRight();
    final int itemMargin = mItemMargin;
    final int colWidth = (getWidth() - paddingLeft - paddingRight - itemMargin * (mColCount - 1)) / mColCount;
    mColWidth = colWidth;
    int rebuildLayoutRecordsBefore = -1;
    int rebuildLayoutRecordsAfter = -1;

    Arrays.fill(mItemBottoms, Integer.MIN_VALUE);

    final int childCount = getChildCount();
    int amountRemoved = 0;

    for (int i = 0; i < childCount; i++) {
        View child = getChildAt(i);
        LayoutParams lp = (LayoutParams) child.getLayoutParams();
        final int col = lp.column;
        final int position = mFirstPosition + i;
        final boolean needsLayout = queryAdapter || child.isLayoutRequested();

        if (queryAdapter) {

            View newView = obtainView(position, child);
            if (newView == null) {
                // child has been removed 
                removeViewAt(i);
                if (i - 1 >= 0)
                    invalidateLayoutRecordsAfterPosition(i - 1);
                amountRemoved++;
                continue;
            } else if (newView != child) {
                removeViewAt(i);
                addView(newView, i);
                child = newView;
            }
            lp = (LayoutParams) child.getLayoutParams(); // Might have changed
        }

        final int span = Math.min(mColCount, lp.span);
        final int widthSize = colWidth * span + itemMargin * (span - 1);

        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);
        }

        int childTop = mItemBottoms[col] > Integer.MIN_VALUE ? mItemBottoms[col] + mItemMargin : child.getTop();

        if (span > 1) {
            int lowest = childTop;
            for (int j = col + 1; j < col + span; j++) {
                final int bottom = mItemBottoms[j] + mItemMargin;
                if (bottom > lowest) {
                    lowest = bottom;
                }
            }
            childTop = lowest;
        }
        final int childHeight = child.getMeasuredHeight();
        final int childBottom = childTop + childHeight;
        final int childLeft = paddingLeft + col * (colWidth + itemMargin);
        final int childRight = childLeft + child.getMeasuredWidth();
        child.layout(childLeft, childTop, childRight, childBottom);

        for (int j = col; j < col + span; j++) {
            mItemBottoms[j] = childBottom;
        }

        final LayoutRecord rec = mLayoutRecords.get(position);
        if (rec != null && rec.height != childHeight) {
            // Invalidate our layout records for everything before this.
            rec.height = childHeight;
            rebuildLayoutRecordsBefore = position;
        }

        if (rec != null && rec.span != span) {
            // Invalidate our layout records for everything after this.
            rec.span = span;
            rebuildLayoutRecordsAfter = position;
        }
    }

    // Update mItemBottoms for any empty columns
    for (int i = 0; i < mColCount; i++) {
        if (mItemBottoms[i] == Integer.MIN_VALUE) {
            mItemBottoms[i] = mItemTops[i];
        }
    }

    if (rebuildLayoutRecordsBefore >= 0 || rebuildLayoutRecordsAfter >= 0) {
        if (rebuildLayoutRecordsBefore >= 0) {
            invalidateLayoutRecordsBeforePosition(rebuildLayoutRecordsBefore);
        }
        if (rebuildLayoutRecordsAfter >= 0) {
            invalidateLayoutRecordsAfterPosition(rebuildLayoutRecordsAfter);
        }
        for (int i = 0; i < (childCount - amountRemoved); i++) {
            final int position = mFirstPosition + i;
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            LayoutRecord rec = mLayoutRecords.get(position);
            if (rec == null) {
                rec = new LayoutRecord();
                mLayoutRecords.put(position, rec);
            }
            rec.column = lp.column;
            rec.height = child.getHeight();
            rec.id = lp.id;
            rec.span = Math.min(mColCount, lp.span);
        }
    }

    if (this.mSelectorPosition != INVALID_POSITION) {
        View child = getChildAt(mMotionPosition - mFirstPosition);
        if (child != null)
            positionSelector(mMotionPosition, child);
    } else if (mTouchMode > TOUCH_MODE_DOWN) {
        View child = getChildAt(mMotionPosition - mFirstPosition);
        if (child != null)
            positionSelector(mMotionPosition, child);
    } else {
        mSelectorRect.setEmpty();
    }
}

From source file:cn.iterlog.myapplication.widget.overscroll.StaggeredGridView.java

/**
 * Measure and layout all currently visible children.
 *
 * @param queryAdapter true to requery the adapter for view data
 *//*from   w ww .  j  a v a  2 s .c om*/
final void layoutChildren(boolean queryAdapter) {
    final int paddingLeft = getPaddingLeft();
    final int paddingRight = getPaddingRight();
    final int itemMargin = mItemMargin;
    final int colWidth = (getWidth() - paddingLeft - paddingRight - itemMargin * (mColCount - 1)) / mColCount;
    mColWidth = colWidth;
    int rebuildLayoutRecordsBefore = -1;
    int rebuildLayoutRecordsAfter = -1;

    Arrays.fill(mItemBottoms, Integer.MIN_VALUE);

    final int childCount = getChildCount();
    int amountRemoved = 0;

    for (int i = 0; i < childCount; i++) {
        View child = getChildAt(i);
        LayoutParams lp = (LayoutParams) child.getLayoutParams();
        final int col = lp.column;
        final int position = mFirstPosition + i;
        final boolean needsLayout = queryAdapter || child.isLayoutRequested();

        if (queryAdapter) {

            View newView = obtainView(position, child);
            if (newView == null) {
                // child has been removed
                removeViewAt(i);
                if (i - 1 >= 0)
                    invalidateLayoutRecordsAfterPosition(i - 1);
                amountRemoved++;
                continue;
            } else if (newView != child) {
                removeViewAt(i);
                addView(newView, i);
                child = newView;
            }
            lp = (LayoutParams) child.getLayoutParams(); // Might have changed
        }

        final int span = Math.min(mColCount, lp.span);
        final int widthSize = colWidth * span + itemMargin * (span - 1);

        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);
        }

        int childTop = mItemBottoms[col] > Integer.MIN_VALUE ? mItemBottoms[col] + mItemMargin : child.getTop();

        if (span > 1) {
            int lowest = childTop;
            for (int j = col + 1; j < col + span; j++) {
                final int bottom = mItemBottoms[j] + mItemMargin;
                if (bottom > lowest) {
                    lowest = bottom;
                }
            }
            childTop = lowest;
        }
        final int childHeight = child.getMeasuredHeight();
        final int childBottom = childTop + childHeight;
        final int childLeft = paddingLeft + col * (colWidth + itemMargin);
        final int childRight = childLeft + child.getMeasuredWidth();
        child.layout(childLeft, childTop, childRight, childBottom);

        for (int j = col; j < col + span; j++) {
            mItemBottoms[j] = childBottom;
        }

        final LayoutRecord rec = mLayoutRecords.get(position);
        if (rec != null && rec.height != childHeight) {
            // Invalidate our layout records for everything before this.
            rec.height = childHeight;
            rebuildLayoutRecordsBefore = position;
        }

        if (rec != null && rec.span != span) {
            // Invalidate our layout records for everything after this.
            rec.span = span;
            rebuildLayoutRecordsAfter = position;
        }
    }

    // Update mItemBottoms for any empty columns
    for (int i = 0; i < mColCount; i++) {
        if (mItemBottoms[i] == Integer.MIN_VALUE) {
            mItemBottoms[i] = mItemTops[i];
        }
    }

    if (rebuildLayoutRecordsBefore >= 0 || rebuildLayoutRecordsAfter >= 0) {
        if (rebuildLayoutRecordsBefore >= 0) {
            invalidateLayoutRecordsBeforePosition(rebuildLayoutRecordsBefore);
        }
        if (rebuildLayoutRecordsAfter >= 0) {
            invalidateLayoutRecordsAfterPosition(rebuildLayoutRecordsAfter);
        }
        for (int i = 0; i < (childCount - amountRemoved); i++) {
            final int position = mFirstPosition + i;
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            LayoutRecord rec = mLayoutRecords.get(position);
            if (rec == null) {
                rec = new LayoutRecord();
                mLayoutRecords.put(position, rec);
            }
            rec.column = lp.column;
            rec.height = child.getHeight();
            rec.id = lp.id;
            rec.span = Math.min(mColCount, lp.span);
        }
    }

    if (this.mSelectorPosition != INVALID_POSITION) {
        View child = getChildAt(mMotionPosition - mFirstPosition);
        if (child != null)
            positionSelector(mMotionPosition, child);
    } else if (mTouchMode > TOUCH_MODE_DOWN) {
        View child = getChildAt(mMotionPosition - mFirstPosition);
        if (child != null)
            positionSelector(mMotionPosition, child);
    } else {
        mSelectorRect.setEmpty();
    }
}

From source file:com.google.android.flexbox.FlexboxHelper.java

/**
 * Calculates how many flex lines are needed in the flex container layout by measuring each
 * child./*from w  w w .j  av a  2  s. c  o  m*/
 * Expanding or shrinking the flex items depending on the flex grow and flex shrink
 * attributes are done in a later procedure, so the views' measured width and measured
 * height may be changed in a later process.
 *
 * @param result           an instance of {@link FlexLinesResult} that is going to contain a
 *                         list of flex lines and the child state used by
 *                         {@link View#setMeasuredDimension(int, int)}.
 * @param mainMeasureSpec  the main axis measure spec imposed by the flex container,
 *                         width for horizontal direction, height otherwise
 * @param crossMeasureSpec the cross axis measure spec imposed by the flex container,
 *                         height for horizontal direction, width otherwise
 * @param needsCalcAmount  the amount of pixels where flex line calculation should be stopped
 *                         this is needed to avoid the expensive calculation if the
 *                         calculation is needed only the small part of the entire flex
 *                         container. (E.g. If the flex container is the
 *                         {@link FlexboxLayoutManager}, the calculation only needs the
 *                         visible area, imposing the entire calculation may cause bad
 *                         performance
 * @param fromIndex        the index of the child from which the calculation starts
 * @param toIndex          the index of the child to which the calculation ends (until the
 *                         flex line which include the which who has that index). If this
 *                         and needsCalcAmount are both set, first flex lines are calculated
 *                         to the index, calculate the amount of pixels as the needsCalcAmount
 *                         argument in addition to that
 * @param existingLines    If not null, calculated flex lines will be added to this instance
 */
void calculateFlexLines(FlexLinesResult result, int mainMeasureSpec, int crossMeasureSpec, int needsCalcAmount,
        int fromIndex, int toIndex, @Nullable List<FlexLine> existingLines) {

    boolean isMainHorizontal = mFlexContainer.isMainAxisDirectionHorizontal();

    int mainMode = View.MeasureSpec.getMode(mainMeasureSpec);
    int mainSize = View.MeasureSpec.getSize(mainMeasureSpec);

    int childState = 0;

    List<FlexLine> flexLines;
    if (existingLines == null) {
        flexLines = new ArrayList<>();
    } else {
        flexLines = existingLines;
    }

    result.mFlexLines = flexLines;

    boolean reachedToIndex = toIndex == NO_POSITION;

    int mainPaddingStart = getPaddingStartMain(isMainHorizontal);
    int mainPaddingEnd = getPaddingEndMain(isMainHorizontal);
    int crossPaddingStart = getPaddingStartCross(isMainHorizontal);
    int crossPaddingEnd = getPaddingEndCross(isMainHorizontal);

    int largestSizeInCross = Integer.MIN_VALUE;

    // The amount of cross size calculated in this method call.
    int sumCrossSize = 0;

    // The index of the view in the flex line.
    int indexInFlexLine = 0;

    FlexLine flexLine = new FlexLine();
    flexLine.mFirstIndex = fromIndex;
    flexLine.mMainSize = mainPaddingStart + mainPaddingEnd;

    int childCount = mFlexContainer.getFlexItemCount();
    for (int i = fromIndex; i < childCount; i++) {
        View child = mFlexContainer.getReorderedFlexItemAt(i);

        if (child == null) {
            if (isLastFlexItem(i, childCount, flexLine)) {
                addFlexLine(flexLines, flexLine, i, sumCrossSize);
            }
            continue;
        } else if (child.getVisibility() == View.GONE) {
            flexLine.mGoneItemCount++;
            flexLine.mItemCount++;
            if (isLastFlexItem(i, childCount, flexLine)) {
                addFlexLine(flexLines, flexLine, i, sumCrossSize);
            }
            continue;
        }

        FlexItem flexItem = (FlexItem) child.getLayoutParams();

        if (flexItem.getAlignSelf() == AlignItems.STRETCH) {
            flexLine.mIndicesAlignSelfStretch.add(i);
        }

        int childMainSize = getFlexItemSizeMain(flexItem, isMainHorizontal);

        if (flexItem.getFlexBasisPercent() != FLEX_BASIS_PERCENT_DEFAULT
                && mainMode == View.MeasureSpec.EXACTLY) {
            childMainSize = Math.round(mainSize * flexItem.getFlexBasisPercent());
            // Use the dimension from the layout if the mainMode is not
            // MeasureSpec.EXACTLY even if any fraction value is set to
            // layout_flexBasisPercent.
        }

        int childMainMeasureSpec;
        int childCrossMeasureSpec;
        if (isMainHorizontal) {
            childMainMeasureSpec = mFlexContainer.getChildWidthMeasureSpec(mainMeasureSpec,
                    mainPaddingStart + mainPaddingEnd + getFlexItemMarginStartMain(flexItem, true)
                            + getFlexItemMarginEndMain(flexItem, true),
                    childMainSize);
            childCrossMeasureSpec = mFlexContainer.getChildHeightMeasureSpec(crossMeasureSpec,
                    crossPaddingStart + crossPaddingEnd + getFlexItemMarginStartCross(flexItem, true)
                            + getFlexItemMarginEndCross(flexItem, true) + sumCrossSize,
                    getFlexItemSizeCross(flexItem, true));
            child.measure(childMainMeasureSpec, childCrossMeasureSpec);
            updateMeasureCache(i, childMainMeasureSpec, childCrossMeasureSpec, child);
        } else {
            childCrossMeasureSpec = mFlexContainer.getChildWidthMeasureSpec(crossMeasureSpec,
                    crossPaddingStart + crossPaddingEnd + getFlexItemMarginStartCross(flexItem, false)
                            + getFlexItemMarginEndCross(flexItem, false) + sumCrossSize,
                    getFlexItemSizeCross(flexItem, false));
            childMainMeasureSpec = mFlexContainer.getChildHeightMeasureSpec(mainMeasureSpec,
                    mainPaddingStart + mainPaddingEnd + getFlexItemMarginStartMain(flexItem, false)
                            + getFlexItemMarginEndMain(flexItem, false),
                    childMainSize);
            child.measure(childCrossMeasureSpec, childMainMeasureSpec);
            updateMeasureCache(i, childCrossMeasureSpec, childMainMeasureSpec, child);
        }
        mFlexContainer.updateViewCache(i, child);

        // Check the size constraint after the first measurement for the child
        // To prevent the child's width/height violate the size constraints imposed by the
        // {@link FlexItem#getMinWidth()}, {@link FlexItem#getMinHeight()},
        // {@link FlexItem#getMaxWidth()} and {@link FlexItem#getMaxHeight()} attributes.
        // E.g. When the child's layout_width is wrap_content the measured width may be
        // less than the min width after the first measurement.
        checkSizeConstraints(child, i);

        childState = View.combineMeasuredStates(childState, child.getMeasuredState());

        if (isWrapRequired(child, mainMode, mainSize, flexLine.mMainSize,
                getViewMeasuredSizeMain(child, isMainHorizontal)
                        + getFlexItemMarginStartMain(flexItem, isMainHorizontal)
                        + getFlexItemMarginEndMain(flexItem, isMainHorizontal),
                flexItem, i, indexInFlexLine, flexLines.size())) {
            if (flexLine.getItemCountNotGone() > 0) {
                addFlexLine(flexLines, flexLine, i > 0 ? i - 1 : 0, sumCrossSize);
                sumCrossSize += flexLine.mCrossSize;
            }

            if (isMainHorizontal) {
                if (flexItem.getHeight() == ViewGroup.LayoutParams.MATCH_PARENT) {
                    // This case takes care of the corner case where the cross size of the
                    // child is affected by the just added flex line.
                    // E.g. when the child's layout_height is set to match_parent, the height
                    // of that child needs to be determined taking the total cross size used
                    // so far into account. In that case, the height of the child needs to be
                    // measured again note that we don't need to judge if the wrapping occurs
                    // because it doesn't change the size along the main axis.
                    childCrossMeasureSpec = mFlexContainer.getChildHeightMeasureSpec(crossMeasureSpec,
                            mFlexContainer.getPaddingTop() + mFlexContainer.getPaddingBottom()
                                    + flexItem.getMarginTop() + flexItem.getMarginBottom() + sumCrossSize,
                            flexItem.getHeight());
                    child.measure(childMainMeasureSpec, childCrossMeasureSpec);
                    checkSizeConstraints(child, i);
                }
            } else {
                if (flexItem.getWidth() == ViewGroup.LayoutParams.MATCH_PARENT) {
                    // This case takes care of the corner case where the cross size of the
                    // child is affected by the just added flex line.
                    // E.g. when the child's layout_width is set to match_parent, the width
                    // of that child needs to be determined taking the total cross size used
                    // so far into account. In that case, the width of the child needs to be
                    // measured again note that we don't need to judge if the wrapping occurs
                    // because it doesn't change the size along the main axis.
                    childCrossMeasureSpec = mFlexContainer.getChildWidthMeasureSpec(crossMeasureSpec,
                            mFlexContainer.getPaddingLeft() + mFlexContainer.getPaddingRight()
                                    + flexItem.getMarginLeft() + flexItem.getMarginRight() + sumCrossSize,
                            flexItem.getWidth());
                    child.measure(childCrossMeasureSpec, childMainMeasureSpec);
                    checkSizeConstraints(child, i);
                }
            }

            flexLine = new FlexLine();
            flexLine.mItemCount = 1;
            flexLine.mMainSize = mainPaddingStart + mainPaddingEnd;
            flexLine.mFirstIndex = i;
            indexInFlexLine = 0;
            largestSizeInCross = Integer.MIN_VALUE;
        } else {
            flexLine.mItemCount++;
            indexInFlexLine++;
        }
        if (mIndexToFlexLine != null) {
            mIndexToFlexLine[i] = flexLines.size();
        }
        flexLine.mMainSize += getViewMeasuredSizeMain(child, isMainHorizontal)
                + getFlexItemMarginStartMain(flexItem, isMainHorizontal)
                + getFlexItemMarginEndMain(flexItem, isMainHorizontal);
        flexLine.mTotalFlexGrow += flexItem.getFlexGrow();
        flexLine.mTotalFlexShrink += flexItem.getFlexShrink();

        mFlexContainer.onNewFlexItemAdded(child, i, indexInFlexLine, flexLine);

        largestSizeInCross = Math.max(largestSizeInCross,
                getViewMeasuredSizeCross(child, isMainHorizontal)
                        + getFlexItemMarginStartCross(flexItem, isMainHorizontal)
                        + getFlexItemMarginEndCross(flexItem, isMainHorizontal)
                        + mFlexContainer.getDecorationLengthCrossAxis(child));
        // Temporarily set the cross axis length as the largest child in the flexLine
        // Expand along the cross axis depending on the mAlignContent property if needed
        // later
        flexLine.mCrossSize = Math.max(flexLine.mCrossSize, largestSizeInCross);

        if (isMainHorizontal) {
            if (mFlexContainer.getFlexWrap() != FlexWrap.WRAP_REVERSE) {
                flexLine.mMaxBaseline = Math.max(flexLine.mMaxBaseline,
                        child.getBaseline() + flexItem.getMarginTop());
            } else {
                // if the flex wrap property is WRAP_REVERSE, calculate the
                // baseline as the distance from the cross end and the baseline
                // since the cross size calculation is based on the distance from the cross end
                flexLine.mMaxBaseline = Math.max(flexLine.mMaxBaseline,
                        child.getMeasuredHeight() - child.getBaseline() + flexItem.getMarginBottom());
            }
        }

        if (isLastFlexItem(i, childCount, flexLine)) {
            addFlexLine(flexLines, flexLine, i, sumCrossSize);
            sumCrossSize += flexLine.mCrossSize;
        }

        if (toIndex != NO_POSITION && flexLines.size() > 0
                && flexLines.get(flexLines.size() - 1).mLastIndex >= toIndex && i >= toIndex
                && !reachedToIndex) {
            // Calculated to include a flex line which includes the flex item having the
            // toIndex.
            // Let the sumCrossSize start from the negative value of the last flex line's
            // cross size because otherwise flex lines aren't calculated enough to fill the
            // visible area.
            sumCrossSize = -flexLine.getCrossSize();
            reachedToIndex = true;
        }
        if (sumCrossSize > needsCalcAmount && reachedToIndex) {
            // Stop the calculation if the sum of cross size calculated reached to the point
            // beyond the needsCalcAmount value to avoid unneeded calculation in a
            // RecyclerView.
            // To be precise, the decoration length may be added to the sumCrossSize,
            // but we omit adding the decoration length because even without the decorator
            // length, it's guaranteed that calculation is done at least beyond the
            // needsCalcAmount
            break;
        }
    }

    result.mChildState = childState;
}