diff options
author | Nicolas Roard <nicolasroard@google.com> | 2018-06-03 23:16:28 -0700 |
---|---|---|
committer | Nicolas Roard <nicolasroard@google.com> | 2018-06-03 23:23:23 -0700 |
commit | 81464d089d5912582e7df5f7a8c0ed468992630f (patch) | |
tree | 1da6df48757a1938c7310b89419ba552949cf40b | |
parent | efb9f6ddf518048b621b33c56788f3f1090884a2 (diff) | |
download | sherpa-81464d089d5912582e7df5f7a8c0ed468992630f.tar.gz |
Fix ratio resolution
Fixes: 77991323
Test: added checks 187,188,189,190,191,192,193
added AdvancedChainTest:testChainLastGone()
added RatioTest:testSimpleWrapRatio()
RatioTest:testSimpleWrapRatio2()
RatioTest:testNestedRatio()
Change-Id: If1cc56456e3bae905d37153d44e6f8b71ea99d27
4 files changed, 190 insertions, 21 deletions
diff --git a/solver/src/main/java/android/support/constraint/solver/widgets/Chain.java b/solver/src/main/java/android/support/constraint/solver/widgets/Chain.java index 9fef62b..b2e8c1e 100644 --- a/solver/src/main/java/android/support/constraint/solver/widgets/Chain.java +++ b/solver/src/main/java/android/support/constraint/solver/widgets/Chain.java @@ -150,7 +150,10 @@ class Chain { } ConstraintAnchor begin = widget.mListAnchors[offset]; - int strength = SolverVariable.STRENGTH_LOW; + int strength = SolverVariable.STRENGTH_HIGHEST; + if (isWrapContent || isChainPacked) { + strength = SolverVariable.STRENGTH_LOW; + } int margin = begin.getMargin(); if (begin.mTarget != null && widget != first) { @@ -333,7 +336,7 @@ class Chain { if (next != null) { beginNextAnchor = next.mListAnchors[offset]; beginNext = beginNextAnchor.mSolverVariable; - beginNextTarget = beginNextAnchor.mTarget != null ? beginNextAnchor.mTarget.mSolverVariable : null; + beginNextTarget = widget.mListAnchors[offset + 1].mSolverVariable; } else { beginNextAnchor = last.mListAnchors[offset + 1].mTarget; if (beginNextAnchor != null) { @@ -430,12 +433,16 @@ class Chain { } - // final centering + // final centering, necessary if the chain is smaller than the available space... if ((isChainSpread || isChainSpreadInside) && firstVisibleWidget != null) { ConstraintAnchor begin = firstVisibleWidget.mListAnchors[offset]; ConstraintAnchor end = lastVisibleWidget.mListAnchors[offset + 1]; SolverVariable beginTarget = begin.mTarget != null ? begin.mTarget.mSolverVariable : null; SolverVariable endTarget = end.mTarget != null ? end.mTarget.mSolverVariable : null; + if (last != lastVisibleWidget) { + ConstraintAnchor realEnd = last.mListAnchors[offset + 1]; + endTarget = realEnd.mTarget != null ? realEnd.mTarget.mSolverVariable : null; + } if (firstVisibleWidget == lastVisibleWidget) { begin = firstVisibleWidget.mListAnchors[offset]; end = firstVisibleWidget.mListAnchors[offset + 1]; diff --git a/solver/src/main/java/android/support/constraint/solver/widgets/ConstraintWidget.java b/solver/src/main/java/android/support/constraint/solver/widgets/ConstraintWidget.java index 85aa836..09b8dc7 100644 --- a/solver/src/main/java/android/support/constraint/solver/widgets/ConstraintWidget.java +++ b/solver/src/main/java/android/support/constraint/solver/widgets/ConstraintWidget.java @@ -2240,12 +2240,25 @@ public class ConstraintWidget { if (mDimensionRatio > 0 && mVisibility != GONE) { useRatio = true; if (mListDimensionBehaviors[DIMENSION_HORIZONTAL] == DimensionBehaviour.MATCH_CONSTRAINT - && mListDimensionBehaviors[DIMENSION_VERTICAL] == DimensionBehaviour.MATCH_CONSTRAINT) { + && mMatchConstraintDefaultWidth == MATCH_CONSTRAINT_SPREAD) { + mMatchConstraintDefaultWidth = MATCH_CONSTRAINT_RATIO; + } + if (mListDimensionBehaviors[DIMENSION_VERTICAL] == DimensionBehaviour.MATCH_CONSTRAINT + && mMatchConstraintDefaultHeight == MATCH_CONSTRAINT_SPREAD) { + mMatchConstraintDefaultHeight = MATCH_CONSTRAINT_RATIO; + } + + if (mListDimensionBehaviors[DIMENSION_HORIZONTAL] == DimensionBehaviour.MATCH_CONSTRAINT + && mListDimensionBehaviors[DIMENSION_VERTICAL] == DimensionBehaviour.MATCH_CONSTRAINT + && mMatchConstraintDefaultWidth == MATCH_CONSTRAINT_RATIO + && mMatchConstraintDefaultHeight == MATCH_CONSTRAINT_RATIO) { setupDimensionRatio(horizontalParentWrapContent, verticalParentWrapContent, horizontalDimensionFixed, verticalDimensionFixed); - } else if (mListDimensionBehaviors[DIMENSION_HORIZONTAL] == DimensionBehaviour.MATCH_CONSTRAINT) { + } else if (mListDimensionBehaviors[DIMENSION_HORIZONTAL] == DimensionBehaviour.MATCH_CONSTRAINT + && mMatchConstraintDefaultWidth == MATCH_CONSTRAINT_RATIO) { mResolvedDimensionRatioSide = HORIZONTAL; width = (int) (mResolvedDimensionRatio * mHeight); - } else if (mListDimensionBehaviors[DIMENSION_VERTICAL] == DimensionBehaviour.MATCH_CONSTRAINT) { + } else if (mListDimensionBehaviors[DIMENSION_VERTICAL] == DimensionBehaviour.MATCH_CONSTRAINT + && mMatchConstraintDefaultHeight == MATCH_CONSTRAINT_RATIO) { mResolvedDimensionRatioSide = VERTICAL; if (mDimensionRatioSide == UNKNOWN) { // need to reverse the ratio as the parsing is done in horizontal mode @@ -2342,13 +2355,6 @@ public class ConstraintWidget { * @param verticalDimensionFixed true if this widget vertical dimension is fixed */ public void setupDimensionRatio(boolean hparentWrapContent, boolean vparentWrapContent, boolean horizontalDimensionFixed, boolean verticalDimensionFixed) { - if (mMatchConstraintDefaultWidth == MATCH_CONSTRAINT_SPREAD) { - mMatchConstraintDefaultWidth = MATCH_CONSTRAINT_RATIO; - } - if (mMatchConstraintDefaultHeight == MATCH_CONSTRAINT_SPREAD) { - mMatchConstraintDefaultHeight = MATCH_CONSTRAINT_RATIO; - } - if (mResolvedDimensionRatioSide == UNKNOWN) { if (horizontalDimensionFixed && !verticalDimensionFixed) { mResolvedDimensionRatioSide = HORIZONTAL; @@ -2396,11 +2402,13 @@ public class ConstraintWidget { } else if (mMatchConstraintMinWidth == 0 && mMatchConstraintMinHeight > 0) { mResolvedDimensionRatio = 1 / mResolvedDimensionRatio; mResolvedDimensionRatioSide = VERTICAL; - } else { - mResolvedDimensionRatio = 1 / mResolvedDimensionRatio; - mResolvedDimensionRatioSide = VERTICAL; } } + + if (mResolvedDimensionRatioSide == UNKNOWN && hparentWrapContent && vparentWrapContent) { + mResolvedDimensionRatio = 1 / mResolvedDimensionRatio; + mResolvedDimensionRatioSide = VERTICAL; + } } /** @@ -2624,7 +2632,7 @@ public class ConstraintWidget { applyCentering = true; applyBoundsCheck = true; int strength = SolverVariable.STRENGTH_HIGHEST; - if (!useRatio) { + if (!useRatio && mResolvedDimensionRatioSide != UNKNOWN) { // useRatio is true if the side we base ourselves on for the ratio is this one // in that case, we need to have a stronger constraint. strength = SolverVariable.STRENGTH_FIXED; diff --git a/solver/src/test/java/android/support/constraint/solver/AdvancedChainTest.java b/solver/src/test/java/android/support/constraint/solver/AdvancedChainTest.java index a9715ec..20436bd 100644 --- a/solver/src/test/java/android/support/constraint/solver/AdvancedChainTest.java +++ b/solver/src/test/java/android/support/constraint/solver/AdvancedChainTest.java @@ -30,6 +30,59 @@ import static org.testng.Assert.assertEquals; public class AdvancedChainTest { @Test + public void testChainLastGone() { + ConstraintWidgetContainer root = new ConstraintWidgetContainer(0, 0, 800, 800); + ConstraintWidget A = new ConstraintWidget(100, 20); + ConstraintWidget B = new ConstraintWidget(100, 20); + ConstraintWidget C = new ConstraintWidget(100, 20); + ConstraintWidget D = new ConstraintWidget(100, 20); + root.setDebugSolverName(root.getSystem(), "root"); + A.setDebugSolverName(root.getSystem(), "A"); + B.setDebugSolverName(root.getSystem(), "B"); + C.setDebugSolverName(root.getSystem(), "C"); + D.setDebugSolverName(root.getSystem(), "D"); + root.add(A); + root.add(B); + root.add(C); + root.add(D); + + A.connect(Type.LEFT, root, Type.LEFT, 0); + A.connect(Type.RIGHT, root, Type.RIGHT, 0); + + B.connect(Type.LEFT, root, Type.LEFT, 0); + B.connect(Type.RIGHT, root, Type.RIGHT, 0); + + C.connect(Type.LEFT, root, Type.LEFT, 0); + C.connect(Type.RIGHT, root, Type.RIGHT, 0); + + D.connect(Type.LEFT, root, Type.LEFT, 0); + D.connect(Type.RIGHT, root, Type.RIGHT, 0); + + A.connect(Type.TOP, root, Type.TOP, 0); + A.connect(Type.BOTTOM, B, Type.TOP, 0); + B.connect(Type.TOP, A, Type.BOTTOM, 0); + B.connect(Type.BOTTOM, C, Type.TOP, 0); + C.connect(Type.TOP, B, Type.BOTTOM, 0); + C.connect(Type.BOTTOM, D, Type.TOP, 0); + D.connect(Type.TOP, C, Type.BOTTOM, 0); + D.connect(Type.BOTTOM, root, Type.BOTTOM, 0); + + B.setVisibility(ConstraintWidget.GONE); + D.setVisibility(ConstraintWidget.GONE); + + root.setOptimizationLevel(Optimizer.OPTIMIZATION_NONE); + root.layout(); + + System.out.println("A: " + A); + System.out.println("B: " + B); + System.out.println("C: " + C); + System.out.println("D: " + D); + + assertEquals(A.getTop(), 253); + assertEquals(C.getTop(), 527); + } + + @Test public void testRatioChainGone() { ConstraintWidgetContainer root = new ConstraintWidgetContainer(0, 0, 800, 800); ConstraintWidget A = new ConstraintWidget(100, 20); diff --git a/solver/src/test/java/android/support/constraint/solver/RatioTest.java b/solver/src/test/java/android/support/constraint/solver/RatioTest.java index 6b474aa..9cc284b 100644 --- a/solver/src/test/java/android/support/constraint/solver/RatioTest.java +++ b/solver/src/test/java/android/support/constraint/solver/RatioTest.java @@ -25,6 +25,107 @@ import static org.testng.Assert.assertEquals; public class RatioTest { + + @Test + public void testSimpleWrapRatio() { + ConstraintWidgetContainer root = new ConstraintWidgetContainer(0, 0, 1000, 1000); + ConstraintWidget A = new ConstraintWidget(100, 20); + root.setDebugName("root"); + root.add(A); + A.setDebugName("A"); + + A.connect(ConstraintAnchor.Type.LEFT, root, ConstraintAnchor.Type.LEFT); + A.connect(ConstraintAnchor.Type.RIGHT, root, ConstraintAnchor.Type.RIGHT); + A.connect(ConstraintAnchor.Type.TOP, root, ConstraintAnchor.Type.TOP); + A.connect(ConstraintAnchor.Type.BOTTOM, root, ConstraintAnchor.Type.BOTTOM); + + + A.setHorizontalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT); + A.setVerticalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT); + + A.setDimensionRatio("1:1"); + root.setOptimizationLevel(Optimizer.OPTIMIZATION_NONE); + root.setVerticalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.WRAP_CONTENT); + root.layout(); + + System.out.println("a) root: " + root + " A: " + A); + assertEquals(root.getWidth(), 1000); + assertEquals(root.getHeight(), 1000); + assertEquals(A.getWidth(), 1000); + assertEquals(A.getHeight(), 1000); + } + + @Test + public void testSimpleWrapRatio2() { + ConstraintWidgetContainer root = new ConstraintWidgetContainer(0, 0, 1000, 1000); + ConstraintWidget A = new ConstraintWidget(100, 20); + root.setDebugName("root"); + root.add(A); + A.setDebugName("A"); + + A.connect(ConstraintAnchor.Type.LEFT, root, ConstraintAnchor.Type.LEFT); + A.connect(ConstraintAnchor.Type.RIGHT, root, ConstraintAnchor.Type.RIGHT); + A.connect(ConstraintAnchor.Type.TOP, root, ConstraintAnchor.Type.TOP); + A.connect(ConstraintAnchor.Type.BOTTOM, root, ConstraintAnchor.Type.BOTTOM); + + + A.setHorizontalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT); + A.setVerticalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT); + + A.setDimensionRatio("1:1"); + root.setOptimizationLevel(Optimizer.OPTIMIZATION_NONE); + root.setHorizontalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.WRAP_CONTENT); + root.layout(); + + System.out.println("a) root: " + root + " A: " + A); + assertEquals(root.getWidth(), 1000); + assertEquals(root.getHeight(), 1000); + assertEquals(A.getWidth(), 1000); + assertEquals(A.getHeight(), 1000); + } + + @Test + public void testNestedRatio() { + ConstraintWidgetContainer root = new ConstraintWidgetContainer(0, 0, 1000, 1000); + ConstraintWidget A = new ConstraintWidget(100, 20); + ConstraintWidget B = new ConstraintWidget(100, 20); + root.setDebugName("root"); + A.setDebugName("A"); + B.setDebugName("B"); + root.add(A); + root.add(B); + A.connect(ConstraintAnchor.Type.LEFT, root, ConstraintAnchor.Type.LEFT); + A.connect(ConstraintAnchor.Type.RIGHT, root, ConstraintAnchor.Type.RIGHT); + A.connect(ConstraintAnchor.Type.TOP, root, ConstraintAnchor.Type.TOP); + A.connect(ConstraintAnchor.Type.BOTTOM, B, ConstraintAnchor.Type.TOP); + + B.connect(ConstraintAnchor.Type.LEFT, A, ConstraintAnchor.Type.LEFT); + B.connect(ConstraintAnchor.Type.RIGHT, A, ConstraintAnchor.Type.RIGHT); + B.connect(ConstraintAnchor.Type.TOP, A, ConstraintAnchor.Type.BOTTOM); + B.connect(ConstraintAnchor.Type.BOTTOM, root, ConstraintAnchor.Type.BOTTOM); + + A.setHorizontalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT); + A.setVerticalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT); + B.setHorizontalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT); + B.setVerticalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT); + + A.setDimensionRatio("1:1"); + B.setDimensionRatio("1:1"); + + root.setOptimizationLevel(Optimizer.OPTIMIZATION_NONE); + root.setHorizontalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.WRAP_CONTENT); + root.layout(); + + System.out.println("a) root: " + root + " A: " + A + " B: " + B); + assertEquals(root.getWidth(), 500); + assertEquals(A.getWidth(), 500); + assertEquals(B.getWidth(), 500); + assertEquals(root.getHeight(), 1000); + assertEquals(A.getHeight(), 500); + assertEquals(B.getHeight(), 500); + } + + @Test public void testBasicCenter() { ConstraintWidgetContainer root = new ConstraintWidgetContainer(0, 0, 1000, 600); @@ -180,18 +281,18 @@ public class RatioTest { root.layout(); System.out.println("a) root: " + root + " A: " + A); int w = (int) (0.7 * root.getWidth()); - assertEquals(A.getLeft(), (root.getWidth() - w) / 2); - assertEquals(A.getTop(), (root.getHeight() - w) / 2); assertEquals(A.getWidth(), w); assertEquals(A.getHeight(), w); + assertEquals(A.getLeft(), (root.getWidth() - w) / 2); + assertEquals(A.getTop(), (root.getHeight() - w) / 2); root.setOptimizationLevel(Optimizer.OPTIMIZATION_STANDARD); root.layout(); System.out.println("b) root: " + root + " A: " + A); - assertEquals(A.getLeft(), (root.getWidth() - w) / 2); - assertEquals(A.getTop(), (root.getHeight() - w) / 2); assertEquals(A.getWidth(), w); assertEquals(A.getHeight(), w); + assertEquals(A.getLeft(), (root.getWidth() - w) / 2); + assertEquals(A.getTop(), (root.getHeight() - w) / 2); } @Test |