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);
    }
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)
@see #setFlexDirection(int)
@see #setFlexWrap(int)
@see #setAlignItems(int)
@see #setAlignContent(int)
common/src/main/java/com/sxjs/common/widget/flexboxlayout/FlexboxLayout.java