/* * MIT License * * Copyright (c) 2016 Alibaba Group * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.alibaba.android.vlayout.layout; import java.util.Arrays; import com.alibaba.android.vlayout.LayoutManagerHelper; import com.alibaba.android.vlayout.OrientationHelperEx; import com.alibaba.android.vlayout.VirtualLayoutManager; import com.alibaba.android.vlayout.VirtualLayoutManager.AnchorInfoWrapper; import com.alibaba.android.vlayout.VirtualLayoutManager.LayoutParams; import com.alibaba.android.vlayout.VirtualLayoutManager.LayoutStateWrapper; import android.graphics.Rect; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.State; import android.view.View; import android.view.View.MeasureSpec; import android.view.ViewGroup; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static com.alibaba.android.vlayout.VirtualLayoutManager.VERTICAL; /** * <pre> * Currently support 1+3(max) layout * 1 + 0 * ------------------------- * | | * | | * | 1 | * | | * | | * | | * ------------------------- * * 1 + 1 * ------------------------- * | | | * | | | * | | | * | 1 | 2 | * | | | * | | | * | | | * ------------------------- * * 1 + 2 * ------------------------- * | | | * | | 2 | * | | | * | 1 |-----------| * | | | * | | 3 | * | | | * ------------------------- * * 1 + 3 * ------------------------- * | | | * | | 2 | * | | | * | 1 |-----------| * | | | | * | | 3 | 4 | * | | | | * ------------------------- * 1 + 4 * ------------------------- * | | | * | | 2 | * | | | * | 1 |-----------| * | | | | | * | | 3 | 4 | 5 | * | | | | | * ------------------------- * </pre> * * @author villadora * @since 1.0.0 */ public class OnePlusNLayoutHelper extends AbstractFullFillLayoutHelper { private static final String TAG = "OnePlusNLayoutHelper"; private Rect mAreaRect = new Rect(); private View[] mChildrenViews; private float[] mColWeights = new float[0]; private float mRowWeight = Float.NaN; public OnePlusNLayoutHelper() { setItemCount(0); } public OnePlusNLayoutHelper(int itemCount) { this(itemCount, 0, 0, 0, 0); } public OnePlusNLayoutHelper(int itemCount, int leftMargin, int topMargin, int rightMargin, int bottomMargin) { setItemCount(itemCount); } /** * {@inheritDoc} * <p/> * Currently, this layout supports maximum children up to 5, otherwise {@link * IllegalArgumentException} * will be thrown * * @param start start position of items handled by this layoutHelper * @param end end position of items handled by this layoutHelper, if end < start or end - * start > 6, it will throw {@link IllegalArgumentException} */ @Override public void onRangeChange(int start, int end) { if (end - start > 6) { throw new IllegalArgumentException( "OnePlusNLayoutHelper only supports maximum 7 children now"); } } public void setColWeights(float[] weights) { if (weights != null) { this.mColWeights = Arrays.copyOf(weights, weights.length); } else { this.mColWeights = new float[0]; } } public void setRowWeight(float weight) { this.mRowWeight = weight; } @Override public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state, LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper) { // reach the end of this layout if (isOutOfRange(layoutState.getCurrentPosition())) { return; } final OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); final boolean layoutInVertical = helper.getOrientation() == VERTICAL; final boolean layoutStart = layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START; final int parentWidth = helper.getContentWidth(); final int parentHeight = helper.getContentHeight(); final int parentHPadding = helper.getPaddingLeft() + helper.getPaddingRight() + getHorizontalMargin() + getHorizontalPadding(); final int parentVPadding = helper.getPaddingTop() + helper.getPaddingBottom() + getVerticalMargin() + getVerticalPadding(); final int currentPosition = layoutState.getCurrentPosition(); if (hasHeader && currentPosition == getRange().getLower()) { View header = nextView(recycler, layoutState, helper, result); int headerConsumed = handleHeader(header, layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); if (header != null) { int left = 0, right = 0, top = 0, bottom = 0; if (layoutInVertical) { if (layoutStart) { bottom = layoutState.getOffset(); top = bottom - headerConsumed; } else { top = layoutState.getOffset() + (mLayoutWithAnchor ? 0 : mMarginTop + mPaddingTop); bottom = top + headerConsumed; } left = helper.getPaddingLeft() + mMarginLeft + mPaddingLeft; right = left + orientationHelper.getDecoratedMeasurementInOther(header); } else { if (layoutStart) { right = layoutState.getOffset(); left = right - headerConsumed; } else { left = layoutState.getOffset() + (mLayoutWithAnchor ? 0 : mMarginLeft + mPaddingLeft); right = left + headerConsumed; } top = helper.getPaddingTop() + mMarginTop + mPaddingTop; bottom = top + orientationHelper.getDecoratedMeasurementInOther(header); } layoutChildWithMargin(header, left, top, right, bottom, helper); } result.mConsumed = headerConsumed; handleStateOnResult(result, header); } else if (hasFooter && currentPosition == getRange().getUpper()) { View footer = nextView(recycler, layoutState, helper, result); int footerConsumed = handleFooter(footer, layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); if (footer != null) { int left = 0, right = 0, top = 0, bottom = 0; if (layoutInVertical) { if (layoutStart) { bottom = layoutState.getOffset() - (mLayoutWithAnchor ? 0 : mMarginBottom + mPaddingBottom); //TODO margin overlap top = bottom - footerConsumed; } else { top = layoutState.getOffset(); bottom = top + footerConsumed; } left = helper.getPaddingLeft() + mMarginLeft + mPaddingLeft; right = left + orientationHelper.getDecoratedMeasurementInOther(footer); } else { if (layoutStart) { right = layoutState.getOffset() - (mLayoutWithAnchor ? 0 : mMarginRight + mPaddingRight); //TODO margin overlap left = right - footerConsumed; } else { left = layoutState.getOffset(); right = left + footerConsumed; } top = helper.getPaddingTop() + mMarginTop + mPaddingTop; bottom = top + orientationHelper.getDecoratedMeasurementInOther(footer); } layoutChildWithMargin(footer, left, top, right, bottom, helper); } result.mConsumed = footerConsumed; handleStateOnResult(result, footer); } else { int contentCount = getItemCount() - (hasHeader ? 1 : 0) - (hasFooter ? 1 : 0); if (mChildrenViews == null || mChildrenViews.length != contentCount) { mChildrenViews = new View[contentCount]; } int count = getAllChildren(mChildrenViews, recycler, layoutState, result, helper); if (count == 0 || count < contentCount) { return; } int mainConsumed = 0; if (contentCount == 1) { mainConsumed = handleOne(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); } else if (contentCount == 2) { mainConsumed = handleTwo(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); } else if (contentCount == 3) { mainConsumed = handleThree(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); } else if (contentCount == 4) { mainConsumed = handleFour(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); } else if (contentCount == 5) { mainConsumed = handleFive(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); } result.mConsumed = mainConsumed; Arrays.fill(mChildrenViews, null); } } private float getViewMainWeight(int index) { if (mColWeights.length > index) { return mColWeights[index]; } return Float.NaN; } @Override protected void onClear(LayoutManagerHelper helper) { super.onClear(helper); } @Override public void checkAnchorInfo(State state, AnchorInfoWrapper anchorInfo, LayoutManagerHelper helper) { super.checkAnchorInfo(state, anchorInfo, helper); mLayoutWithAnchor = true; } @Override public int computeAlignOffset(int offset, boolean isLayoutEnd, boolean useAnchor, LayoutManagerHelper helper) { //Log.d(TAG, // "range " + getRange() + " offset " + offset + " isLayoutEnd " + isLayoutEnd + " useAnchor " + useAnchor // + " helper " + this.hashCode()); final boolean layoutInVertical = helper.getOrientation() == LinearLayoutManager.VERTICAL; if (useAnchor) { return 0; } if (isLayoutEnd) { if (offset == getItemCount() - 1) { return layoutInVertical ? mMarginBottom + mPaddingBottom : mMarginRight + mPaddingRight; } } else { if (offset == 0) { return layoutInVertical ? -mMarginTop - mPaddingTop : -mMarginLeft - mPaddingLeft; } } return 0; } private int handleHeader(View header, LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { if (header == null) { return 0; } OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); final VirtualLayoutManager.LayoutParams lp = (LayoutParams) header.getLayoutParams(); // fill width int widthSpec = helper.getChildMeasureSpec(parentWidth - parentHPadding, layoutInVertical ? MATCH_PARENT : lp.width, !layoutInVertical); int heightSpec = helper.getChildMeasureSpec(parentHeight - parentVPadding, layoutInVertical ? lp.height : MeasureSpec.EXACTLY, layoutInVertical); helper.measureChildWithMargins(header, widthSpec, heightSpec); return orientationHelper.getDecoratedMeasurement(header); } private int handleFooter(View footer, LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { if (footer == null) { return 0; } OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); final VirtualLayoutManager.LayoutParams lp = (LayoutParams) footer.getLayoutParams(); // fill width int widthSpec = helper.getChildMeasureSpec(parentWidth - parentHPadding, layoutInVertical ? MATCH_PARENT : lp.width, !layoutInVertical); int heightSpec = helper.getChildMeasureSpec(parentHeight - parentVPadding, layoutInVertical ? lp.height : MeasureSpec.EXACTLY, layoutInVertical); helper.measureChildWithMargins(footer, widthSpec, heightSpec); return orientationHelper.getDecoratedMeasurement(footer); } private int handleOne(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { int mainConsumed = 0; OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); View view = mChildrenViews[0]; final VirtualLayoutManager.LayoutParams lp = (LayoutParams) view.getLayoutParams(); if (!Float.isNaN(mAspectRatio)) { if (layoutInVertical) { lp.height = (int) ((parentWidth - parentHPadding) / mAspectRatio); } else { lp.width = (int) ((parentHeight - parentVPadding) * mAspectRatio); } } final float weight = getViewMainWeight(0); // fill width int widthSpec = helper.getChildMeasureSpec( Float.isNaN(weight) ? (parentWidth - parentHPadding) : (int) ((parentWidth - parentHPadding) * weight), layoutInVertical ? MATCH_PARENT : lp.width, !layoutInVertical); int heightSpec = helper.getChildMeasureSpec(parentHeight - parentVPadding, layoutInVertical ? lp.height : MeasureSpec.EXACTLY, layoutInVertical); helper.measureChildWithMargins(view, widthSpec, heightSpec); mainConsumed += orientationHelper.getDecoratedMeasurement(view); calculateRect(mainConsumed, mAreaRect, layoutState, helper); layoutChildWithMargin(view, mAreaRect.left, mAreaRect.top, mAreaRect.right, mAreaRect.bottom, helper); handleStateOnResult(result, view); mainConsumed = mAreaRect.bottom - mAreaRect.top + (hasHeader ? 0 : mMarginTop + mPaddingTop) + (hasFooter ? 0 : mMarginBottom + mPaddingBottom); return mainConsumed; } private int handleTwo(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { int mainConsumed = 0; OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); final View child1 = mChildrenViews[0]; final VirtualLayoutManager.LayoutParams lp1 = (VirtualLayoutManager.LayoutParams) child1.getLayoutParams(); final View child2 = mChildrenViews[1]; final VirtualLayoutManager.LayoutParams lp2 = (VirtualLayoutManager.LayoutParams) child2.getLayoutParams(); final float weight1 = getViewMainWeight(0); final float weight2 = getViewMainWeight(1); if (layoutInVertical) { if (!Float.isNaN(mAspectRatio)) { lp1.height = lp2.height = (int) ((parentWidth - parentHPadding) / mAspectRatio); } lp2.topMargin = lp1.topMargin; lp2.bottomMargin = lp1.bottomMargin; int availableSpace = parentWidth - parentHPadding - lp1.leftMargin - lp1.rightMargin - lp2.leftMargin - lp2.rightMargin; int width1 = Float.isNaN(weight1) ? (int) (availableSpace / 2.0f + 0.5f) : (int) (availableSpace * weight1 / 100 + 0.5f); int width2 = Float.isNaN(weight2) ? (availableSpace - width1) : (int) (availableSpace * weight2 / 100 + 0.5f); helper.measureChildWithMargins(child1, MeasureSpec.makeMeasureSpec(width1 + lp1.leftMargin + lp1.rightMargin, MeasureSpec.EXACTLY), helper.getChildMeasureSpec(helper.getContentHeight(), lp1.height, true)); helper.measureChildWithMargins(child2, MeasureSpec.makeMeasureSpec(width2 + lp2.leftMargin + lp2.rightMargin, MeasureSpec.EXACTLY), helper.getChildMeasureSpec(helper.getContentHeight(), lp2.height, true)); mainConsumed += Math.max(orientationHelper.getDecoratedMeasurement(child1), orientationHelper.getDecoratedMeasurement(child2)); calculateRect(mainConsumed, mAreaRect, layoutState, helper); int right1 = mAreaRect.left + orientationHelper .getDecoratedMeasurementInOther(child1); layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top, right1, mAreaRect.bottom, helper); layoutChildWithMargin(child2, right1, mAreaRect.top, right1 + orientationHelper.getDecoratedMeasurementInOther(child2), mAreaRect.bottom, helper); mainConsumed = mAreaRect.bottom - mAreaRect.top + (hasHeader ? 0 : mMarginTop + mPaddingTop) + (hasFooter ? 0 : mMarginBottom + mPaddingBottom); } else { if (!Float.isNaN(mAspectRatio)) { lp1.width = lp2.width = (int) ((parentHeight - parentVPadding) * mAspectRatio); } int availableSpace = parentHeight - parentVPadding - lp1.topMargin - lp1.bottomMargin - lp2.topMargin - lp2.bottomMargin; int height1 = Float.isNaN(weight1) ? (int) (availableSpace / 2.0f + 0.5f) : (int) (availableSpace * weight1 / 100 + 0.5f); int height2 = Float.isNaN(weight2) ? (int) (availableSpace - height1) : (int) (availableSpace * weight2 / 100 + 0.5f); helper.measureChildWithMargins(child1, helper.getChildMeasureSpec(helper.getContentWidth(), lp1.width, true), MeasureSpec.makeMeasureSpec(height1 + lp1.topMargin + lp1.bottomMargin, MeasureSpec.EXACTLY)); int width = child1.getMeasuredWidth(); helper.measureChildWithMargins(child2, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height2 + lp2.topMargin + lp2.bottomMargin, MeasureSpec.EXACTLY)); mainConsumed += Math.max(orientationHelper.getDecoratedMeasurement(child1), orientationHelper.getDecoratedMeasurement(child2)); calculateRect(mainConsumed, mAreaRect, layoutState, helper); int bottom1 = mAreaRect.top + orientationHelper .getDecoratedMeasurementInOther(child1); layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top, mAreaRect.right, bottom1, helper); layoutChildWithMargin(child2, mAreaRect.left, bottom1, mAreaRect.right, bottom1 + orientationHelper.getDecoratedMeasurementInOther(child2), helper); mainConsumed = mAreaRect.right - mAreaRect.left + (hasHeader ? 0 : mMarginLeft + mPaddingRight) + (hasFooter ? 0 : mMarginRight + mPaddingRight); } handleStateOnResult(result, mChildrenViews); return mainConsumed; } private int handleThree(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { int mainConsumed = 0; OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); final View child1 = mChildrenViews[0]; final VirtualLayoutManager.LayoutParams lp1 = (VirtualLayoutManager.LayoutParams) child1.getLayoutParams(); final View child2 = helper.getReverseLayout() ? mChildrenViews[2] : mChildrenViews[1]; final View child3 = helper.getReverseLayout() ? mChildrenViews[1] : mChildrenViews[2]; final VirtualLayoutManager.LayoutParams lp2 = (VirtualLayoutManager.LayoutParams) child2.getLayoutParams(); final VirtualLayoutManager.LayoutParams lp3 = (VirtualLayoutManager.LayoutParams) child3.getLayoutParams(); final float weight1 = getViewMainWeight(0); final float weight2 = getViewMainWeight(1); final float weight3 = getViewMainWeight(2); if (layoutInVertical) { if (!Float.isNaN(mAspectRatio)) { lp1.height = (int) ((parentWidth - parentHPadding) / mAspectRatio); } // make border consistent lp2.topMargin = lp1.topMargin; lp3.bottomMargin = lp1.bottomMargin; lp3.leftMargin = lp2.leftMargin; lp3.rightMargin = lp2.rightMargin; int availableSpace = parentWidth - parentHPadding - lp1.leftMargin - lp1.rightMargin - lp2.leftMargin - lp2.rightMargin; int width1 = Float.isNaN(weight1) ? (int) (availableSpace / 2.0f + 0.5f) : (int) (availableSpace * weight1 / 100 + 0.5f); int width2 = Float.isNaN(weight2) ? (int) (availableSpace - width1) : (int) (availableSpace * weight2 / 100 + 0.5); int width3 = Float.isNaN(weight3) ? (int) (width2) : (int) (availableSpace * weight3 / 100 + 0.5); helper.measureChildWithMargins(child1, MeasureSpec.makeMeasureSpec(width1 + lp1.leftMargin + lp1.rightMargin, MeasureSpec.EXACTLY), helper.getChildMeasureSpec(helper.getContentHeight(), lp1.height, true)); int height1 = child1.getMeasuredHeight(); int height2 = Float.isNaN(mRowWeight) ? (int) ((height1 - lp2.bottomMargin - lp3.topMargin) / 2.0f + 0.5f) : (int) ((height1 - lp2.bottomMargin - lp3.topMargin) * mRowWeight / 100 + 0.5f); int height3 = height1 - lp2.bottomMargin - lp3.topMargin - height2; helper.measureChildWithMargins(child2, MeasureSpec.makeMeasureSpec(width2 + lp2.leftMargin + lp2.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height2 + lp2.topMargin + lp2.bottomMargin, MeasureSpec.EXACTLY)); helper.measureChildWithMargins(child3, MeasureSpec.makeMeasureSpec(width3 + lp3.leftMargin + lp3.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height3 + lp3.topMargin + lp3.bottomMargin, MeasureSpec.EXACTLY)); mainConsumed += Math.max(height1 + lp1.topMargin + lp1.bottomMargin, height2 + lp2.topMargin + lp2.bottomMargin + height3 + lp3.topMargin + lp3.bottomMargin); calculateRect(mainConsumed, mAreaRect, layoutState, helper); int right1 = mAreaRect.left + orientationHelper .getDecoratedMeasurementInOther(child1); layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top, right1, mAreaRect.bottom, helper); int right2 = right1 + orientationHelper.getDecoratedMeasurementInOther(child2); layoutChildWithMargin(child2, right1, mAreaRect.top, right2, mAreaRect.top + child2.getMeasuredHeight() + lp2.topMargin + lp2.bottomMargin, helper); layoutChildWithMargin(child3, right1, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child3), right1 + orientationHelper.getDecoratedMeasurementInOther(child3), mAreaRect.bottom, helper); mainConsumed = mAreaRect.bottom - mAreaRect.top + (hasHeader ? 0 : mMarginTop + mPaddingTop) + (hasFooter ? 0 : mMarginBottom + mPaddingBottom); } else { // TODO: horizontal support } handleStateOnResult(result, mChildrenViews); return mainConsumed; } private int handleFour(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { int mainConsumed = 0; OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); final View child1 = mChildrenViews[0]; final VirtualLayoutManager.LayoutParams lp1 = (VirtualLayoutManager.LayoutParams) child1.getLayoutParams(); final View child2 = helper.getReverseLayout() ? mChildrenViews[3] : mChildrenViews[1]; final VirtualLayoutManager.LayoutParams lp2 = (VirtualLayoutManager.LayoutParams) child2.getLayoutParams(); final View child3 = mChildrenViews[2]; final VirtualLayoutManager.LayoutParams lp3 = (VirtualLayoutManager.LayoutParams) child3.getLayoutParams(); final View child4 = helper.getReverseLayout() ? mChildrenViews[1] : mChildrenViews[3]; final VirtualLayoutManager.LayoutParams lp4 = (VirtualLayoutManager.LayoutParams) child4.getLayoutParams(); final float weight1 = getViewMainWeight(0); final float weight2 = getViewMainWeight(1); final float weight3 = getViewMainWeight(2); final float weight4 = getViewMainWeight(3); if (layoutInVertical) { lp2.topMargin = lp1.topMargin; lp3.bottomMargin = lp4.bottomMargin = lp1.bottomMargin; lp3.leftMargin = lp2.leftMargin; lp4.rightMargin = lp2.rightMargin; if (!Float.isNaN(mAspectRatio)) { lp1.height = (int) ((parentWidth - parentHPadding) / mAspectRatio); } int availableSpace = parentWidth - parentHPadding - lp1.leftMargin - lp1.rightMargin - lp2.leftMargin - lp2.rightMargin; int width1 = Float.isNaN(weight1) ? (int) (availableSpace / 2.0f + 0.5f) : (int) (availableSpace * weight1 / 100 + 0.5f); int width2 = Float.isNaN(weight2) ? (int) (availableSpace - width1) : (int) (availableSpace * weight2 / 100 + 0.5f); int width3 = Float.isNaN(weight3) ? (int) ( (width2 - lp3.rightMargin - lp4.leftMargin) / 2.0f + 0.5f) : (int) (availableSpace * weight3 / 100 + 0.5f); int width4 = Float.isNaN(weight4) ? (int) ((width2 - lp3.rightMargin - lp4.leftMargin - width3)) : (int) (availableSpace * weight4 / 100 + 0.5f); helper.measureChildWithMargins(child1, MeasureSpec.makeMeasureSpec(width1 + lp1.leftMargin + lp1.rightMargin, MeasureSpec.EXACTLY), helper.getChildMeasureSpec(helper.getContentHeight(), lp1.height, true)); int height1 = child1.getMeasuredHeight(); int height2 = Float.isNaN(mRowWeight) ? (int) ((height1 - lp2.bottomMargin - lp3.topMargin) / 2.0f + 0.5f) : (int) ((height1 - lp2.bottomMargin - lp3.topMargin) * mRowWeight / 100 + 0.5f); int height3 = (int) ((height1 - lp2.bottomMargin - lp3.topMargin) - height2); helper.measureChildWithMargins(child2, MeasureSpec.makeMeasureSpec(width2 + lp2.leftMargin + lp2.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height2 + lp2.topMargin + lp2.bottomMargin, MeasureSpec.EXACTLY)); helper.measureChildWithMargins(child3, MeasureSpec.makeMeasureSpec(width3 + lp3.leftMargin + lp3.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height3 + lp3.topMargin + lp3.bottomMargin, MeasureSpec.EXACTLY)); helper.measureChildWithMargins(child4, MeasureSpec.makeMeasureSpec(width4 + lp4.leftMargin + lp4.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height3 + lp4.topMargin + lp4.bottomMargin, MeasureSpec.EXACTLY)); mainConsumed += Math.max(height1 + lp1.topMargin + lp1.bottomMargin, height2 + lp2.topMargin + lp2.bottomMargin + Math .max(height3 + lp3.topMargin + lp3.bottomMargin, height3 + lp4.topMargin + lp4.bottomMargin)); calculateRect(mainConsumed, mAreaRect, layoutState, helper); int right1 = mAreaRect.left + orientationHelper .getDecoratedMeasurementInOther(child1); layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top, right1, mAreaRect.bottom, helper); int right2 = right1 + orientationHelper.getDecoratedMeasurementInOther(child2); layoutChildWithMargin(child2, right1, mAreaRect.top, right2, mAreaRect.top + orientationHelper.getDecoratedMeasurement(child2), helper); int right3 = right1 + orientationHelper.getDecoratedMeasurementInOther(child3); layoutChildWithMargin(child3, right1, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child3), right3, mAreaRect.bottom, helper); layoutChildWithMargin(child4, right3, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child4), right3 + orientationHelper.getDecoratedMeasurementInOther(child4), mAreaRect.bottom, helper); mainConsumed = mAreaRect.bottom - mAreaRect.top + (hasHeader ? 0 : mMarginTop + mPaddingTop) + (hasFooter ? 0 : mMarginBottom + mPaddingBottom); } else { // TODO: horizontal support } handleStateOnResult(result, mChildrenViews); return mainConsumed; } private int handleFive(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { int mainConsumed = 0; OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); final View child1 = mChildrenViews[0]; final VirtualLayoutManager.LayoutParams lp1 = (VirtualLayoutManager.LayoutParams) child1.getLayoutParams(); final View child2 = helper.getReverseLayout() ? mChildrenViews[4] : mChildrenViews[1]; final VirtualLayoutManager.LayoutParams lp2 = (VirtualLayoutManager.LayoutParams) child2.getLayoutParams(); final View child3 = helper.getReverseLayout() ? mChildrenViews[3] : mChildrenViews[2]; final VirtualLayoutManager.LayoutParams lp3 = (VirtualLayoutManager.LayoutParams) child3.getLayoutParams(); final View child4 = helper.getReverseLayout() ? mChildrenViews[2] : mChildrenViews[3]; final VirtualLayoutManager.LayoutParams lp4 = (VirtualLayoutManager.LayoutParams) child4.getLayoutParams(); final View child5 = helper.getReverseLayout() ? mChildrenViews[1] : mChildrenViews[4]; final VirtualLayoutManager.LayoutParams lp5 = (VirtualLayoutManager.LayoutParams) child5.getLayoutParams(); final float weight1 = getViewMainWeight(0); final float weight2 = getViewMainWeight(1); final float weight3 = getViewMainWeight(2); final float weight4 = getViewMainWeight(3); final float weight5 = getViewMainWeight(4); if (layoutInVertical) { lp2.topMargin = lp1.topMargin; lp3.bottomMargin = lp4.bottomMargin = lp1.bottomMargin; lp3.leftMargin = lp2.leftMargin; lp4.rightMargin = lp2.rightMargin; lp5.rightMargin = lp2.rightMargin; if (!Float.isNaN(mAspectRatio)) { lp1.height = (int) ((parentWidth - parentHPadding) / mAspectRatio); } int availableSpace = parentWidth - parentHPadding - lp1.leftMargin - lp1.rightMargin - lp2.leftMargin - lp2.rightMargin; int width1 = Float.isNaN(weight1) ? (int) (availableSpace / 2.0f + 0.5f) : (int) (availableSpace * weight1 / 100 + 0.5f); int width2 = Float.isNaN(weight2) ? (int) (availableSpace - width1) : (int) (availableSpace * weight2 / 100 + 0.5f); int width3 = Float.isNaN(weight3) ? (int) ( (width2 - lp3.rightMargin - lp4.leftMargin) / 3.0f + 0.5f) : (int) (availableSpace * weight3 / 100 + 0.5f); int width4 = Float.isNaN(weight4) ? (int) ( (width2 - lp3.rightMargin - lp4.leftMargin) / 3.0f + 0.5f) : (int) (availableSpace * weight4 / 100 + 0.5f); int width5 = Float.isNaN(weight5) ? (int) ((width2 - lp3.rightMargin - lp4.leftMargin - width3 - width4)) : (int) (availableSpace * weight5 / 100 + 0.5f); helper.measureChildWithMargins(child1, MeasureSpec.makeMeasureSpec(width1 + lp1.leftMargin + lp1.rightMargin, MeasureSpec.EXACTLY), helper.getChildMeasureSpec(helper.getContentHeight(), lp1.height, true)); int height1 = child1.getMeasuredHeight(); int height2 = Float.isNaN(mRowWeight) ? (int) ((height1 - lp2.bottomMargin - lp3.topMargin) / 2.0f + 0.5f) : (int) ((height1 - lp2.bottomMargin - lp3.topMargin) * mRowWeight / 100 + 0.5f); int height3 = (int) ((height1 - lp2.bottomMargin - lp3.topMargin) - height2); helper.measureChildWithMargins(child2, MeasureSpec.makeMeasureSpec(width2 + lp2.leftMargin + lp2.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height2 + lp2.topMargin + lp2.bottomMargin, MeasureSpec.EXACTLY)); helper.measureChildWithMargins(child3, MeasureSpec.makeMeasureSpec(width3 + lp3.leftMargin + lp3.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height3 + lp3.topMargin + lp3.bottomMargin, MeasureSpec.EXACTLY)); helper.measureChildWithMargins(child4, MeasureSpec.makeMeasureSpec(width4 + lp4.leftMargin + lp4.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height3 + lp4.topMargin + lp4.bottomMargin, MeasureSpec.EXACTLY)); helper.measureChildWithMargins(child5, MeasureSpec.makeMeasureSpec(width5 + lp5.leftMargin + lp5.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height3 + lp5.topMargin + lp5.bottomMargin, MeasureSpec.EXACTLY)); mainConsumed += Math.max(height1 + lp1.topMargin + lp1.bottomMargin, height2 + lp2.topMargin + lp2.bottomMargin + Math .max(height3 + lp3.topMargin + lp3.bottomMargin, height3 + lp4.topMargin + lp4.bottomMargin)); calculateRect(mainConsumed, mAreaRect, layoutState, helper); int right1 = mAreaRect.left + orientationHelper.getDecoratedMeasurementInOther(child1); layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top, right1, mAreaRect.bottom, helper); int right2 = right1 + orientationHelper.getDecoratedMeasurementInOther(child2); layoutChildWithMargin(child2, right1, mAreaRect.top, right2, mAreaRect.top + orientationHelper.getDecoratedMeasurement(child2), helper); int right3 = right1 + orientationHelper.getDecoratedMeasurementInOther(child3); layoutChildWithMargin(child3, right1, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child3), right3, mAreaRect.bottom, helper); int right4 = right3 + orientationHelper.getDecoratedMeasurementInOther(child4); layoutChildWithMargin(child4, right3, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child4), right3 + orientationHelper.getDecoratedMeasurementInOther(child4), mAreaRect.bottom, helper); layoutChildWithMargin(child5, right4, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child5), right4 + orientationHelper.getDecoratedMeasurementInOther(child5), mAreaRect.bottom, helper); mainConsumed = mAreaRect.bottom - mAreaRect.top + (hasHeader ? 0 : mMarginTop + mPaddingTop) + (hasFooter ? 0 : mMarginBottom + mPaddingBottom); } else { // TODO: horizontal support } handleStateOnResult(result, mChildrenViews); return mainConsumed; } }