From 54dfa5d90e49037eba05f5278076b45428b2bd11 Mon Sep 17 00:00:00 2001 From: Chris Wren Date: Tue, 24 Apr 2012 09:50:03 -0400 Subject: [PATCH] Don't allow children of a SizeAdaptiveLayout to measure outside their declared range of valid sizes. Bug: 6377749 Change-Id: Ie706006eee9c0ed8dda468212a652941b8e20be0 --- .../internal/widget/SizeAdaptiveLayout.java | 28 +++++++++++++-- .../coretests/res/layout/size_adaptive_lies.xml | 40 ++++++++++++++++++++++ .../internal/widget/SizeAdaptiveLayoutTest.java | 34 +++++++++++++++++- 3 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 core/tests/coretests/res/layout/size_adaptive_lies.xml diff --git a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java index 0a99f174fdc3..bbf55092c801 100644 --- a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java +++ b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java @@ -16,6 +16,8 @@ package com.android.internal.widget; +import java.lang.Math; + import com.android.internal.R; import android.animation.Animator; @@ -157,9 +159,29 @@ public class SizeAdaptiveLayout extends ViewGroup { int childState = combineMeasuredStates(0, model.getMeasuredState()); if (DEBUG) Log.d(TAG, "measured child at: " + childHeight); int resolvedWidth = resolveSizeAndState(childWidth, widthMeasureSpec, childState); - int resolvedheight = resolveSizeAndState(childHeight, heightMeasureSpec, childState); - setMeasuredDimension(resolvedWidth, resolvedheight); - if (DEBUG) Log.d(TAG, "resolved to: " + resolvedheight); + int resolvedHeight = resolveSizeAndState(childHeight, heightMeasureSpec, childState); + if (DEBUG) Log.d(TAG, "resolved to: " + resolvedHeight); + int boundedHeight = clampSizeToBounds(resolvedHeight, model); + if (DEBUG) Log.d(TAG, "bounded to: " + boundedHeight); + setMeasuredDimension(resolvedWidth, boundedHeight); + } + + private int clampSizeToBounds(int measuredHeight, View child) { + SizeAdaptiveLayout.LayoutParams lp = + (SizeAdaptiveLayout.LayoutParams) child.getLayoutParams(); + int heightIn = View.MEASURED_SIZE_MASK & measuredHeight; + int height = Math.max(heightIn, lp.minHeight); + if (lp.maxHeight != SizeAdaptiveLayout.LayoutParams.UNBOUNDED) { + height = Math.min(height, lp.maxHeight); + } + + if (heightIn != height) { + Log.d(TAG, this + "child view " + child + " " + + "measured out of bounds at " + heightIn +"px " + + "clamped to " + height + "px"); + } + + return height; } //TODO extend to width and height diff --git a/core/tests/coretests/res/layout/size_adaptive_lies.xml b/core/tests/coretests/res/layout/size_adaptive_lies.xml new file mode 100644 index 000000000000..7de892e23f63 --- /dev/null +++ b/core/tests/coretests/res/layout/size_adaptive_lies.xml @@ -0,0 +1,40 @@ + + + + + + + + + diff --git a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java index a937f6570569..efd06bfbc13c 100644 --- a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java +++ b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java @@ -449,10 +449,42 @@ public class SizeAdaptiveLayoutTest extends AndroidTestCase { panel.getBackground() instanceof ColorDrawable); } + @SmallTest + public void testOpenSmallEvenWhenLargeIsActuallySmall() { + inflate(R.layout.size_adaptive_lies); + SizeAdaptiveLayout.LayoutParams lp = + (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams(); + int height = (int) lp.minHeight; + + measureAndLayout(height); + + assertEquals("1U should be visible", + View.VISIBLE, + mSmallView.getVisibility()); + assertTrue("1U should also have been measured", + mSmallView.getMeasuredHeight() > 0); + } + + @SmallTest + public void testOpenLargeEvenWhenLargeIsActuallySmall() { + inflate(R.layout.size_adaptive_lies); + SizeAdaptiveLayout.LayoutParams lp = + (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); + int height = (int) lp.minHeight; + + measureAndLayout(height); + + assertEquals("4U should be visible", + View.VISIBLE, + mLargeView.getVisibility()); + assertTrue("4U should also have been measured", + mLargeView.getMeasuredHeight() > 0); + } + private void measureAndLayout(int height) { // manually measure it, and lay it out int measureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST); mSizeAdaptiveLayout.measure(500, measureSpec); - mSizeAdaptiveLayout.layout(0, 0, 500, height); + mSizeAdaptiveLayout.layout(0, 0, 500, mSizeAdaptiveLayout.getMeasuredHeight()); } } -- 2.11.0