private void invalidateMathCache() { mRootConstraints.invalidate(); for (int i = 0; i < getChildCount(); i++) { final ViewConstraints viewConstraints = mViewConstraints[i]; viewConstraints.invalidate(); } }
private void updateChildrenSize(final int widthMeasureSpec, final int heightMeasureSpec) { for (int i = 0; i < getChildCount(); i++) { final ViewConstraints viewConstraints = mViewConstraints[i]; final View v = viewConstraints.getView(); final LayoutParams layoutParams = (LayoutParams) v.getLayoutParams(); final int mL = layoutParams.leftMargin, mR = layoutParams.rightMargin, mT = layoutParams.topMargin, mB = layoutParams.bottomMargin; measureChildWithMargins(v, widthMeasureSpec, 0, heightMeasureSpec, 0); if (!viewConstraints.isHorizontalSpring()) { Value childWidth; if (v.getVisibility() == View.GONE) { childWidth = mLayoutMath.variable(0); } else if (layoutParams.relativeWidth > 0) { childWidth = mRootConstraints .innerRight .subtract(mRootConstraints.innerLeft) .multiply(mLayoutMath.variable(layoutParams.relativeWidth)) .divide(mLayoutMath.variable(RELATIVE_SIZE_DENOMINATOR)); } else { childWidth = mLayoutMath.variable(v.getMeasuredWidth()); } viewConstraints.leftMargin.setValue(mL); viewConstraints.rightMargin.setValue(mR); Value outerWidth = childWidth.add(mLayoutMath.variable(mL + mR)).retain(); viewConstraints.setWidth(outerWidth); outerWidth.release(); } if (!viewConstraints.isVerticalSpring()) { Value childHeight; if (v.getVisibility() == View.GONE) { childHeight = mLayoutMath.variable(0); } else if (layoutParams.relativeHeight > 0) { childHeight = mRootConstraints .innerBottom .subtract(mRootConstraints.innerTop) .multiply(mLayoutMath.variable(layoutParams.relativeHeight)) .divide(mLayoutMath.variable(RELATIVE_SIZE_DENOMINATOR)); } else { childHeight = mLayoutMath.variable(v.getMeasuredHeight()); } viewConstraints.topMargin.setValue(mT); viewConstraints.bottomMargin.setValue(mB); Value outerHeight = childHeight.add(mLayoutMath.variable(mT + mB)).retain(); viewConstraints.setHeight(outerHeight); outerHeight.release(); } } }
private void cacheLayoutPositions() { for (int i = 0; i < getChildCount(); i++) { final ViewConstraints viewConstraints = mViewConstraints[i]; final View v = viewConstraints.getView(); if (viewConstraints.isHorizontalSpring() && !viewConstraints.isHorizontalSpringUsed()) { throw new IllegalStateException( "Horizontal weight defined but never used, please review your layout. Remember that the chain of views cannot divert when using springs: Problematic view (please also check other dependant views): " + v + ", problematic layout: " + this); } else if (viewConstraints.isVerticalSpring() && !viewConstraints.isVerticalSpringUsed()) { throw new IllegalStateException( "Vertical weight defined but never used, please review your layout. Remember that the chain of views cannot divert when using springs: Problematic view (please also check other dependant views): " + v + ", problematic layout: " + this); } else { int anchor = 0; try { LayoutParams st = (LayoutParams) v.getLayoutParams(); anchor = LEFT; st.left = viewConstraints.innerLeft.getValue(); anchor = RIGHT; st.right = viewConstraints.innerRight.getValue(); anchor = TOP; st.top = viewConstraints.innerTop.getValue(); anchor = BOTTOM; st.bottom = viewConstraints.innerBottom.getValue(); v.measure( MeasureSpec.makeMeasureSpec(st.right - st.left, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(st.bottom - st.top, MeasureSpec.EXACTLY)); } catch (IllegalStateException e) { throw new IllegalStateException( "View " + ANCHOR_NAMES[anchor] + " position could not be calculated, please review your layout. Remember that A.above = B and B.below = A are not equivalent in terms of calculation order, please refer to documentation. Problematic view (please also check other dependant views): " + v + ", problematic layout: " + this, e); } catch (StackOverflowError e) { throw new IllegalStateException( "Constraints of a view could not be resolved (circular dependency), please review your layout. Problematic view (please also check other dependant views): " + v + ", problematic layout: " + this); } } } }
private void handleSprings( final Stack<ViewConstraints> springMetrics, final boolean isWrapContentWidth, final boolean isWrapContentHeight) { if (!springMetrics.isEmpty()) { mHorizontalChains.clear(); mVerticalChains.clear(); while (!springMetrics.isEmpty()) { final ViewConstraints spring = springMetrics.pop(); final ViewConstraints chainHeadX = getChainHorizontalHead(spring); final ViewConstraints chainHeadY = getChainVerticalHead(spring); if (chainHeadX != null) { if (isWrapContentWidth && mMinWidth <= 0) { throw new IllegalStateException( "Horizontal springs not supported when layout width is wrap_content"); } mHorizontalChains.add(chainHeadX); } if (chainHeadY != null) { if (isWrapContentHeight && mMinHeight <= 0) { throw new IllegalStateException( "Vertical springs not supported when layout height is wrap_content and minHeight is not defined"); } mVerticalChains.add(chainHeadY); } } for (int i = 0; i < mHorizontalChains.size(); i++) { final ViewConstraints chainHead = mHorizontalChains.get(i); int totalWeight = 0; Value contentWidth = mLayoutMath.variable(0); final ValueWrapper totalWeightWrapper = mLayoutMath.wrap(); final ValueWrapper chainWidthWrapper = mLayoutMath.wrap(); ViewConstraints chainElem = chainHead, prevElem = null; Value start = chainElem.left, end; while (chainElem != null) { if (chainElem.isHorizontalSpring()) { chainElem.markHorizontalSpringUsed(); final int weight = ((LayoutParams) chainElem.getView().getLayoutParams()).widthWeight; totalWeight += weight; final Value width = chainWidthWrapper .multiply(mLayoutMath.variable(weight)) .divide(totalWeightWrapper) .max(mLayoutMath.variable(0)) .retain(); chainElem.setWidth(width); width.release(); } else { contentWidth = contentWidth.add(chainElem.getWidth()); } prevElem = chainElem; chainElem = chainElem.nextX; } end = prevElem.right; totalWeightWrapper.setValueObject(mLayoutMath.variable(totalWeight)); chainWidthWrapper.setValueObject(end.subtract(start).subtract(contentWidth)); } for (int i = 0; i < mVerticalChains.size(); i++) { final ViewConstraints chainHead = mVerticalChains.get(i); int totalWeight = 0; Value contentHeight = mLayoutMath.variable(0); final ValueWrapper totalWeightWrapper = mLayoutMath.wrap(); final ValueWrapper chainWidthWrapper = mLayoutMath.wrap(); ViewConstraints chainElem = chainHead, prevElem = null; Value start = chainElem.top, end; while (chainElem != null) { if (chainElem.isVerticalSpring()) { chainElem.markVerticalSpringUsed(); final int weight = ((LayoutParams) chainElem.getView().getLayoutParams()).heightWeight; totalWeight += weight; final Value height = chainWidthWrapper .multiply(mLayoutMath.variable(weight)) .divide(totalWeightWrapper) .max(mLayoutMath.variable(0)) .retain(); chainElem.setHeight(height); height.release(); } else { contentHeight = contentHeight.add(chainElem.getHeight()); } prevElem = chainElem; chainElem = chainElem.nextY; } end = prevElem.bottom; totalWeightWrapper.setValueObject(mLayoutMath.variable(totalWeight)); chainWidthWrapper.setValueObject(end.subtract(start).subtract(contentHeight)); } } }
private void createViewMetrics(Stack<ViewConstraints> springMetrics) { springMetrics.clear(); mIdToViewConstraints.clear(); if (mRootConstraints != null) { mRootConstraints.release(); for (ViewConstraints mViewConstraint : mViewConstraints) { mViewConstraint.release(); } mRootConstraints.reset(this); resizeViewConstraintsArray(getChildCount()); } else { mRootConstraints = new ViewConstraints(this, mLayoutMath); mViewConstraints = new ViewConstraints[getChildCount()]; } mRootConstraints.left.setValueObject(mLayoutMath.variable(0)); mRootConstraints.top.setValueObject(mLayoutMath.variable(0)); final int count = getChildCount(); for (int i = 0; i < count; i++) { final View v = getChildAt(i); mIdToViewConstraints.append(v.getId(), i); if (mViewConstraints[i] == null) { mViewConstraints[i] = new ViewConstraints(v, mLayoutMath); } else { mViewConstraints[i].reset(v); } } for (int i = 0; i < count; i++) { final ViewConstraints viewConstraints = mViewConstraints[i]; final LayoutParams layoutParams = (LayoutParams) viewConstraints.getView().getLayoutParams(); if (layoutParams.getWidthWeight() > 0) { viewConstraints.markAsHorizontalSpring(); } if (layoutParams.getHeightWeight() > 0) { viewConstraints.markAsVerticalSpring(); } int[] childRules = layoutParams.getRelations(); for (int relation : VALID_RELATIONS) { final ViewConstraints metrics = getViewMetrics(childRules[relation]); if (metrics != null) { metrics.updateRelation(viewConstraints, relation); } } if (viewConstraints.isHorizontalSpring() || viewConstraints.isVerticalSpring()) { springMetrics.add(viewConstraints); } } }