Example usage for android.view View getBaseline

List of usage examples for android.view View getBaseline

Introduction

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

Prototype

@ViewDebug.ExportedProperty(category = "layout")
public int getBaseline() 

Source Link

Document

Return the offset of the widget's text baseline from the widget's top boundary.

Usage

From source file:com.cxsplay.wallyskim.widget.flexbox.FlexboxLayout.java

/**
 * Place a single View when the layout direction is horizontal ({@link #mFlexDirection} is
 * either {@link #FLEX_DIRECTION_ROW} or {@link #FLEX_DIRECTION_ROW_REVERSE}).
 *
 * @param view       the View to be placed
 * @param flexLine   the {@link FlexLine} where the View belongs to
 * @param flexWrap   the flex wrap attribute of this FlexboxLayout
 * @param alignItems the align items attribute of this FlexboxLayout
 * @param left       the left position of the View, which the View's margin is already taken
 *                   into account//w  ww.j av  a 2  s.  c o  m
 * @param top        the top position of the flex line where the View belongs to. The actual
 *                   View's top position is shifted depending on the flexWrap and alignItems
 *                   attributes
 * @param right      the right position of the View, which the View's margin is already taken
 *                   into account
 * @param bottom     the bottom position of the flex line where the View belongs to. The actual
 *                   View's bottom position is shifted depending on the flexWrap and alignItems
 *                   attributes
 * @see #getAlignItems()
 * @see #setAlignItems(int)
 * @see LayoutParams#alignSelf
 */
private void layoutSingleChildHorizontal(View view, FlexLine flexLine, @FlexWrap int flexWrap, int alignItems,
        int left, int top, int right, int bottom) {
    LayoutParams lp = (LayoutParams) view.getLayoutParams();
    if (lp.alignSelf != LayoutParams.ALIGN_SELF_AUTO) {
        // Expecting the values for alignItems and alignSelf match except for ALIGN_SELF_AUTO.
        // Assigning the alignSelf value as alignItems should work.
        alignItems = lp.alignSelf;
    }
    int crossSize = flexLine.mCrossSize;
    switch (alignItems) {
    case ALIGN_ITEMS_FLEX_START: // Intentional fall through
    case ALIGN_ITEMS_STRETCH:
        if (flexWrap != FLEX_WRAP_WRAP_REVERSE) {
            view.layout(left, top + lp.topMargin, right, bottom + lp.topMargin);
        } else {
            view.layout(left, top - lp.bottomMargin, right, bottom - lp.bottomMargin);
        }
        break;
    case ALIGN_ITEMS_BASELINE:
        if (flexWrap != FLEX_WRAP_WRAP_REVERSE) {
            int marginTop = flexLine.mMaxBaseline - view.getBaseline();
            marginTop = Math.max(marginTop, lp.topMargin);
            view.layout(left, top + marginTop, right, bottom + marginTop);
        } else {
            int marginBottom = flexLine.mMaxBaseline - view.getMeasuredHeight() + view.getBaseline();
            marginBottom = Math.max(marginBottom, lp.bottomMargin);
            view.layout(left, top - marginBottom, right, bottom - marginBottom);
        }
        break;
    case ALIGN_ITEMS_FLEX_END:
        if (flexWrap != FLEX_WRAP_WRAP_REVERSE) {
            view.layout(left, top + crossSize - view.getMeasuredHeight() - lp.bottomMargin, right,
                    top + crossSize - lp.bottomMargin);
        } else {
            // If the flexWrap == FLEX_WRAP_WRAP_REVERSE, the direction of the
            // flexEnd is flipped (from top to bottom).
            view.layout(left, top - crossSize + view.getMeasuredHeight() + lp.topMargin, right,
                    bottom - crossSize + view.getMeasuredHeight() + lp.topMargin);
        }
        break;
    case ALIGN_ITEMS_CENTER:
        int topFromCrossAxis = (crossSize - view.getMeasuredHeight() + lp.topMargin - lp.bottomMargin) / 2;
        if (flexWrap != FLEX_WRAP_WRAP_REVERSE) {
            view.layout(left, top + topFromCrossAxis, right, top + topFromCrossAxis + view.getMeasuredHeight());
        } else {
            view.layout(left, top - topFromCrossAxis, right, top - topFromCrossAxis + view.getMeasuredHeight());
        }
        break;
    }
}

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)/* ww  w .j  a  va 2  s.c om*/
 * @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.v7.widget.LinearLayoutCompat.java

/**
 * Measures the children when the orientation of this LinearLayout is set
 * to {@link #HORIZONTAL}.// w  ww  .ja  v a2 s  . co 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 measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
    mTotalLength = 0;
    int maxHeight = 0;
    int childState = 0;
    int alternativeMaxHeight = 0;
    int weightedMaxHeight = 0;
    boolean allFillParent = true;
    float totalWeight = 0;

    final int count = getVirtualChildCount();

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

    boolean matchHeight = false;
    boolean skippedMeasure = false;

    if (mMaxAscent == null || mMaxDescent == null) {
        mMaxAscent = new int[VERTICAL_GRAVITY_COUNT];
        mMaxDescent = new int[VERTICAL_GRAVITY_COUNT];
    }

    final int[] maxAscent = mMaxAscent;
    final int[] maxDescent = mMaxDescent;

    maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1;
    maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1;

    final boolean baselineAligned = mBaselineAligned;
    final boolean useLargestChild = mUseLargestChild;

    final boolean isExactly = widthMode == MeasureSpec.EXACTLY;

    int largestChildWidth = Integer.MIN_VALUE;

    // See how wide everyone is. Also remember max height.
    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;
        }

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

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

        totalWeight += lp.weight;

        if (widthMode == MeasureSpec.EXACTLY && lp.width == 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.
            if (isExactly) {
                mTotalLength += lp.leftMargin + lp.rightMargin;
            } else {
                final int totalLength = mTotalLength;
                mTotalLength = Math.max(totalLength, totalLength + lp.leftMargin + lp.rightMargin);
            }

            // Baseline alignment requires to measure widgets to obtain the
            // baseline offset (in particular for TextViews). The following
            // defeats the optimization mentioned above. Allow the child to
            // use as much space as it wants because we can shrink things
            // later (and re-measure).
            if (baselineAligned) {
                final int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
                child.measure(freeSpec, freeSpec);
            } else {
                skippedMeasure = true;
            }
        } else {
            int oldWidth = Integer.MIN_VALUE;

            if (lp.width == 0 && lp.weight > 0) {
                // widthMode 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 width of 0
                oldWidth = 0;
                lp.width = 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, totalWeight == 0 ? mTotalLength : 0,
                    heightMeasureSpec, 0);

            if (oldWidth != Integer.MIN_VALUE) {
                lp.width = oldWidth;
            }

            final int childWidth = child.getMeasuredWidth();
            if (isExactly) {
                mTotalLength += childWidth + lp.leftMargin + lp.rightMargin + getNextLocationOffset(child);
            } else {
                final int totalLength = mTotalLength;
                mTotalLength = Math.max(totalLength, totalLength + childWidth + lp.leftMargin + lp.rightMargin
                        + getNextLocationOffset(child));
            }

            if (useLargestChild) {
                largestChildWidth = Math.max(childWidth, largestChildWidth);
            }
        }

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

        final int margin = lp.topMargin + lp.bottomMargin;
        final int childHeight = child.getMeasuredHeight() + margin;
        childState = ViewUtils.combineMeasuredStates(childState, ViewCompat.getMeasuredState(child));

        if (baselineAligned) {
            final int childBaseline = child.getBaseline();
            if (childBaseline != -1) {
                // Translates the child's vertical gravity into an index
                // in the range 0..VERTICAL_GRAVITY_COUNT
                final int gravity = (lp.gravity < 0 ? mGravity : lp.gravity) & Gravity.VERTICAL_GRAVITY_MASK;
                final int index = ((gravity >> Gravity.AXIS_Y_SHIFT) & ~Gravity.AXIS_SPECIFIED) >> 1;

                maxAscent[index] = Math.max(maxAscent[index], childBaseline);
                maxDescent[index] = Math.max(maxDescent[index], childHeight - childBaseline);
            }
        }

        maxHeight = Math.max(maxHeight, childHeight);

        allFillParent = allFillParent && lp.height == LayoutParams.MATCH_PARENT;
        if (lp.weight > 0) {
            /*
             * Heights of weighted Views are bogus if we end up
             * remeasuring, so keep them separate.
             */
            weightedMaxHeight = Math.max(weightedMaxHeight, matchHeightLocally ? margin : childHeight);
        } else {
            alternativeMaxHeight = Math.max(alternativeMaxHeight, matchHeightLocally ? margin : childHeight);
        }

        i += getChildrenSkipCount(child, i);
    }

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

    // Check mMaxAscent[INDEX_TOP] first because it maps to Gravity.TOP,
    // the most common case
    if (maxAscent[INDEX_TOP] != -1 || maxAscent[INDEX_CENTER_VERTICAL] != -1 || maxAscent[INDEX_BOTTOM] != -1
            || maxAscent[INDEX_FILL] != -1) {
        final int ascent = Math.max(maxAscent[INDEX_FILL], Math.max(maxAscent[INDEX_CENTER_VERTICAL],
                Math.max(maxAscent[INDEX_TOP], maxAscent[INDEX_BOTTOM])));
        final int descent = Math.max(maxDescent[INDEX_FILL], Math.max(maxDescent[INDEX_CENTER_VERTICAL],
                Math.max(maxDescent[INDEX_TOP], maxDescent[INDEX_BOTTOM])));
        maxHeight = Math.max(maxHeight, ascent + descent);
    }

    if (useLargestChild && (widthMode == MeasureSpec.AT_MOST || widthMode == 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();
            if (isExactly) {
                mTotalLength += largestChildWidth + lp.leftMargin + lp.rightMargin
                        + getNextLocationOffset(child);
            } else {
                final int totalLength = mTotalLength;
                mTotalLength = Math.max(totalLength, totalLength + largestChildWidth + lp.leftMargin
                        + lp.rightMargin + getNextLocationOffset(child));
            }
        }
    }

    // Add in our padding
    mTotalLength += getPaddingLeft() + getPaddingRight();

    int widthSize = mTotalLength;

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

    // Reconcile our calculated size with the widthMeasureSpec
    int widthSizeAndState = ViewCompat.resolveSizeAndState(widthSize, widthMeasureSpec, 0);
    widthSize = widthSizeAndState & 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 = widthSize - mTotalLength;
    if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
        float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;

        maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1;
        maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1;
        maxHeight = -1;

        mTotalLength = 0;

        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 said it could absorb extra space -- give him his share
                int share = (int) (childExtra * delta / weightSum);
                weightSum -= childExtra;
                delta -= share;

                final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
                        getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin, lp.height);

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

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

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

            if (isExactly) {
                mTotalLength += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin
                        + getNextLocationOffset(child);
            } else {
                final int totalLength = mTotalLength;
                mTotalLength = Math.max(totalLength, totalLength + child.getMeasuredWidth() + lp.leftMargin
                        + lp.rightMargin + getNextLocationOffset(child));
            }

            boolean matchHeightLocally = heightMode != MeasureSpec.EXACTLY
                    && lp.height == LayoutParams.MATCH_PARENT;

            final int margin = lp.topMargin + lp.bottomMargin;
            int childHeight = child.getMeasuredHeight() + margin;
            maxHeight = Math.max(maxHeight, childHeight);
            alternativeMaxHeight = Math.max(alternativeMaxHeight, matchHeightLocally ? margin : childHeight);

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

            if (baselineAligned) {
                final int childBaseline = child.getBaseline();
                if (childBaseline != -1) {
                    // Translates the child's vertical gravity into an index in the range 0..2
                    final int gravity = (lp.gravity < 0 ? mGravity : lp.gravity)
                            & Gravity.VERTICAL_GRAVITY_MASK;
                    final int index = ((gravity >> Gravity.AXIS_Y_SHIFT) & ~Gravity.AXIS_SPECIFIED) >> 1;

                    maxAscent[index] = Math.max(maxAscent[index], childBaseline);
                    maxDescent[index] = Math.max(maxDescent[index], childHeight - childBaseline);
                }
            }
        }

        // Add in our padding
        mTotalLength += getPaddingLeft() + getPaddingRight();
        // TODO: Should we update widthSize with the new total length?

        // Check mMaxAscent[INDEX_TOP] first because it maps to Gravity.TOP,
        // the most common case
        if (maxAscent[INDEX_TOP] != -1 || maxAscent[INDEX_CENTER_VERTICAL] != -1
                || maxAscent[INDEX_BOTTOM] != -1 || maxAscent[INDEX_FILL] != -1) {
            final int ascent = Math.max(maxAscent[INDEX_FILL], Math.max(maxAscent[INDEX_CENTER_VERTICAL],
                    Math.max(maxAscent[INDEX_TOP], maxAscent[INDEX_BOTTOM])));
            final int descent = Math.max(maxDescent[INDEX_FILL], Math.max(maxDescent[INDEX_CENTER_VERTICAL],
                    Math.max(maxDescent[INDEX_TOP], maxDescent[INDEX_BOTTOM])));
            maxHeight = Math.max(maxHeight, ascent + descent);
        }
    } else {
        alternativeMaxHeight = Math.max(alternativeMaxHeight, weightedMaxHeight);

        // We have no limit, so make all weighted views as wide as the largest child.
        // Children will have already been measured once.
        if (useLargestChild && widthMode != 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(largestChildWidth, MeasureSpec.EXACTLY),
                            MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY));
                }
            }
        }
    }

    if (!allFillParent && heightMode != MeasureSpec.EXACTLY) {
        maxHeight = alternativeMaxHeight;
    }

    maxHeight += getPaddingTop() + getPaddingBottom();

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

    setMeasuredDimension(widthSizeAndState | (childState & ViewCompat.MEASURED_STATE_MASK),
            ViewCompat.resolveSizeAndState(maxHeight, heightMeasureSpec,
                    (childState << ViewCompat.MEASURED_HEIGHT_STATE_SHIFT)));

    if (matchHeight) {
        forceUniformHeight(count, widthMeasureSpec);
    }
}

From source file:com.uzmap.pkg.uzmodules.uzUIChatBox.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)/*ww w  .j a v  a 2 s .co  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();

        // The index of the view in a same flex line.
        int indexInFlexLine = 0;
        flexLine.mMainSize = 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.mItemCount++;
                addFlexLineIfLastFlexItem(i, childCount, flexLine);
                continue;
            }

            LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (lp.alignSelf == LayoutParams.ALIGN_SELF_STRETCH) {
                flexLine.mIndicesAlignSelfStretch.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(widthMode, widthSize, flexLine.mMainSize,
                    child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin, lp, i, indexInFlexLine)) {
                if (flexLine.mItemCount > 0) {
                    addFlexLine(flexLine);
                }

                flexLine = new FlexLine();
                flexLine.mItemCount = 1;
                flexLine.mMainSize = paddingStart + paddingEnd;
                largestHeightInRow = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
                indexInFlexLine = 0;
            } else {
                flexLine.mItemCount++;
                indexInFlexLine++;
            }
            flexLine.mMainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            flexLine.mTotalFlexGrow += lp.flexGrow;
            flexLine.mTotalFlexShrink += 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.mCrossSize = Math.max(flexLine.mCrossSize, largestHeightInRow);

            // Check if the beginning or middle divider is required for the flex item
            if (hasDividerBeforeChildAtAlongMainAxis(i, indexInFlexLine)) {
                flexLine.mMainSize += mDividerVerticalWidth;
                flexLine.mDividerLengthInMainSize += mDividerVerticalWidth;
            }

            if (mFlexWrap != FLEX_WRAP_WRAP_REVERSE) {
                flexLine.mMaxBaseline = Math.max(flexLine.mMaxBaseline, 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.mMaxBaseline = Math.max(flexLine.mMaxBaseline,
                        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.mItemCount; i++) {
                View child = getReorderedChildAt(i);
                LayoutParams lp = (LayoutParams) child.getLayoutParams();
                if (mFlexWrap != FLEX_WRAP_WRAP_REVERSE) {
                    int marginTop = flexLine.mMaxBaseline - child.getBaseline();
                    marginTop = Math.max(marginTop, lp.topMargin);
                    largestHeightInLine = Math.max(largestHeightInLine,
                            child.getHeight() + marginTop + lp.bottomMargin);
                } else {
                    int marginBottom = flexLine.mMaxBaseline - child.getMeasuredHeight() + child.getBaseline();
                    marginBottom = Math.max(marginBottom, lp.bottomMargin);
                    largestHeightInLine = Math.max(largestHeightInLine,
                            child.getHeight() + lp.topMargin + marginBottom);
                }
            }
            flexLine.mCrossSize = largestHeightInLine;
            viewIndex += flexLine.mItemCount;
        }
    }

    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:com.google.android.flexbox.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)//w  ww  .  j ava  2s .  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();

        // The index of the view in a same flex line.
        int indexInFlexLine = 0;
        flexLine.mMainSize = 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.mItemCount++;
                addFlexLineIfLastFlexItem(i, childCount, flexLine);
                continue;
            }

            FlexboxLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (lp.alignSelf == LayoutParams.ALIGN_SELF_STRETCH) {
                flexLine.mIndicesAlignSelfStretch.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(widthMode, widthSize, flexLine.mMainSize,
                    child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin, lp, i, indexInFlexLine)) {
                if (flexLine.mItemCount > 0) {
                    addFlexLine(flexLine);
                }

                flexLine = new FlexLine();
                flexLine.mItemCount = 1;
                flexLine.mMainSize = paddingStart + paddingEnd;
                largestHeightInRow = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
                indexInFlexLine = 0;
            } else {
                flexLine.mItemCount++;
                indexInFlexLine++;
            }
            flexLine.mMainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            flexLine.mTotalFlexGrow += lp.flexGrow;
            flexLine.mTotalFlexShrink += 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.mCrossSize = Math.max(flexLine.mCrossSize, largestHeightInRow);

            // Check if the beginning or middle divider is required for the flex item
            if (hasDividerBeforeChildAtAlongMainAxis(i, indexInFlexLine)) {
                flexLine.mMainSize += mDividerVerticalWidth;
                flexLine.mDividerLengthInMainSize += mDividerVerticalWidth;
            }

            if (mFlexWrap != FLEX_WRAP_WRAP_REVERSE) {
                flexLine.mMaxBaseline = Math.max(flexLine.mMaxBaseline, 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.mMaxBaseline = Math.max(flexLine.mMaxBaseline,
                        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.mItemCount; i++) {
                View child = getReorderedChildAt(i);
                LayoutParams lp = (LayoutParams) child.getLayoutParams();
                if (mFlexWrap != FLEX_WRAP_WRAP_REVERSE) {
                    int marginTop = flexLine.mMaxBaseline - child.getBaseline();
                    marginTop = Math.max(marginTop, lp.topMargin);
                    largestHeightInLine = Math.max(largestHeightInLine,
                            child.getHeight() + marginTop + lp.bottomMargin);
                } else {
                    int marginBottom = flexLine.mMaxBaseline - child.getMeasuredHeight() + child.getBaseline();
                    marginBottom = Math.max(marginBottom, lp.bottomMargin);
                    largestHeightInLine = Math.max(largestHeightInLine,
                            child.getHeight() + lp.topMargin + marginBottom);
                }
            }
            flexLine.mCrossSize = largestHeightInLine;
            viewIndex += flexLine.mItemCount;
        }
    }

    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:org.nativescript.widgets.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)/* w w  w . j  a  v a 2 s . co  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();

        // The index of the view in a same flex line.
        int indexInFlexLine = 0;
        flexLine.mMainSize = 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.mItemCount++;
                addFlexLineIfLastFlexItem(i, childCount, flexLine);
                continue;
            }

            FlexboxLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (lp.alignSelf == LayoutParams.ALIGN_SELF_STRETCH) {
                flexLine.mIndicesAlignSelfStretch.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 < 0 ? LayoutParams.WRAP_CONTENT : childWidth);
            int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
                    getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin,
                    lp.height < 0 ? LayoutParams.WRAP_CONTENT : 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(widthMode, widthSize, flexLine.mMainSize,
                    child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin, lp, i, indexInFlexLine)) {
                if (flexLine.mItemCount > 0) {
                    addFlexLine(flexLine);
                }

                flexLine = new FlexLine();
                flexLine.mItemCount = 1;
                flexLine.mMainSize = paddingStart + paddingEnd;
                largestHeightInRow = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
                indexInFlexLine = 0;
            } else {
                flexLine.mItemCount++;
                indexInFlexLine++;
            }
            flexLine.mMainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            flexLine.mTotalFlexGrow += lp.flexGrow;
            flexLine.mTotalFlexShrink += 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.mCrossSize = Math.max(flexLine.mCrossSize, largestHeightInRow);

            // Check if the beginning or middle divider is required for the flex item
            if (hasDividerBeforeChildAtAlongMainAxis(i, indexInFlexLine)) {
                flexLine.mMainSize += mDividerVerticalWidth;
                flexLine.mDividerLengthInMainSize += mDividerVerticalWidth;
            }

            if (mFlexWrap != FLEX_WRAP_WRAP_REVERSE) {
                flexLine.mMaxBaseline = Math.max(flexLine.mMaxBaseline, 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.mMaxBaseline = Math.max(flexLine.mMaxBaseline,
                        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.mItemCount; i++) {
                View child = getReorderedChildAt(i);
                LayoutParams lp = (LayoutParams) child.getLayoutParams();
                if (mFlexWrap != FLEX_WRAP_WRAP_REVERSE) {
                    int marginTop = flexLine.mMaxBaseline - child.getBaseline();
                    marginTop = Math.max(marginTop, lp.topMargin);
                    largestHeightInLine = Math.max(largestHeightInLine,
                            child.getHeight() + marginTop + lp.bottomMargin);
                } else {
                    int marginBottom = flexLine.mMaxBaseline - child.getMeasuredHeight() + child.getBaseline();
                    marginBottom = Math.max(marginBottom, lp.bottomMargin);
                    largestHeightInLine = Math.max(largestHeightInLine,
                            child.getHeight() + lp.topMargin + marginBottom);
                }
            }
            flexLine.mCrossSize = largestHeightInLine;
            viewIndex += flexLine.mItemCount;
        }
    }

    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:com.cxsplay.wallyskim.widget.flexbox.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)//w ww.  ja  v  a2s .  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();

        // The index of the view in a same flex line.
        int indexInFlexLine = 0;
        flexLine.mMainSize = 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.mItemCount++;
                flexLine.mGoneItemCount++;
                addFlexLineIfLastFlexItem(i, childCount, flexLine);
                continue;
            }

            FlexboxLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (lp.alignSelf == LayoutParams.ALIGN_SELF_STRETCH) {
                flexLine.mIndicesAlignSelfStretch.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(widthMode, widthSize, flexLine.mMainSize,
                    child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin, lp, i, indexInFlexLine)) {
                if (flexLine.getItemCountNotGone() > 0) {
                    addFlexLine(flexLine);
                }

                flexLine = new FlexLine();
                flexLine.mItemCount = 1;
                flexLine.mMainSize = paddingStart + paddingEnd;
                largestHeightInRow = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
                indexInFlexLine = 0;
            } else {
                flexLine.mItemCount++;
                indexInFlexLine++;
            }
            flexLine.mMainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            flexLine.mTotalFlexGrow += lp.flexGrow;
            flexLine.mTotalFlexShrink += 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.mCrossSize = Math.max(flexLine.mCrossSize, largestHeightInRow);

            // Check if the beginning or middle divider is required for the flex item
            if (hasDividerBeforeChildAtAlongMainAxis(i, indexInFlexLine)) {
                flexLine.mMainSize += mDividerVerticalWidth;
                flexLine.mDividerLengthInMainSize += mDividerVerticalWidth;
            }

            if (mFlexWrap != FLEX_WRAP_WRAP_REVERSE) {
                flexLine.mMaxBaseline = Math.max(flexLine.mMaxBaseline, 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.mMaxBaseline = Math.max(flexLine.mMaxBaseline,
                        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.mItemCount; i++) {
                View child = getReorderedChildAt(i);
                LayoutParams lp = (LayoutParams) child.getLayoutParams();
                if (mFlexWrap != FLEX_WRAP_WRAP_REVERSE) {
                    int marginTop = flexLine.mMaxBaseline - child.getBaseline();
                    marginTop = Math.max(marginTop, lp.topMargin);
                    largestHeightInLine = Math.max(largestHeightInLine,
                            child.getHeight() + marginTop + lp.bottomMargin);
                } else {
                    int marginBottom = flexLine.mMaxBaseline - child.getMeasuredHeight() + child.getBaseline();
                    marginBottom = Math.max(marginBottom, lp.bottomMargin);
                    largestHeightInLine = Math.max(largestHeightInLine,
                            child.getHeight() + lp.topMargin + marginBottom);
                }
            }
            flexLine.mCrossSize = largestHeightInLine;
            viewIndex += flexLine.mItemCount;
        }
    }

    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:com.google.android.flexbox.FlexboxHelper.java

/**
 * Calculates how many flex lines are needed in the flex container layout by measuring each
 * child./*from w  ww  .j  a v  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;
}