OSDN Git Service

Check targetSdkVersion when passing size hints for UNSPECIFIED specs
authorAdam Powell <adamp@google.com>
Thu, 11 Jun 2015 20:19:24 +0000 (13:19 -0700)
committerAdam Powell <adamp@google.com>
Thu, 11 Jun 2015 20:57:41 +0000 (13:57 -0700)
As of MNC stock widgets will pass a size in UNSPECIFIED MeasureSpec
values as a hint of the container size. This lets things like list items
size themselves at 1/3 the size of their container.

This breaks assumptions in a few existing applications, so maintain the
old expectation of 0 size in UNSPECIFIED MeasureSpecs for apps targeting
older SDK versions.

Bug 20975083

Change-Id: Ic7318e88854e00d96852dde2c0e10376b42bf77f

12 files changed:
core/java/android/view/View.java
core/java/android/view/ViewGroup.java
core/java/android/widget/FastScroller.java
core/java/android/widget/GridView.java
core/java/android/widget/LinearLayout.java
core/java/android/widget/ListView.java
core/java/android/widget/ScrollView.java
core/java/android/widget/Spinner.java
core/java/android/widget/TabWidget.java
core/java/android/widget/TableRow.java
core/java/com/android/internal/widget/ActionBarContextView.java
core/java/com/android/internal/widget/SlidingTab.java

index be372d0..d2ee0e5 100644 (file)
@@ -741,6 +741,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     private static boolean sUseBrokenMakeMeasureSpec = false;
 
     /**
+     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
+     */
+    static boolean sUseZeroUnspecifiedMeasureSpec = false;
+
+    /**
      * Ignore any optimizations using the measure cache.
      */
     private static boolean sIgnoreMeasureCache = false;
@@ -3796,6 +3801,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
 
             Canvas.sCompatibilityRestore = targetSdkVersion < MNC;
 
+            // In MNC and newer, our widgets can pass a "hint" value in the size
+            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
+            // know what the expected parent size is going to be, so e.g. list items can size
+            // themselves at 1/3 the size of their container. It breaks older apps though,
+            // specifically apps that use some popular open source libraries.
+            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < MNC;
+
             sCompatibilityDone = true;
         }
     }
@@ -21032,6 +21044,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
         }
 
         /**
+         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
+         * will automatically get a size of 0. Older apps expect this.
+         *
+         * @hide internal use only for compatibility with system widgets and older apps
+         */
+        public static int makeSafeMeasureSpec(int size, int mode) {
+            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
+                return 0;
+            }
+            return makeMeasureSpec(size, mode);
+        }
+
+        /**
          * Extracts the mode from the supplied measure specification.
          *
          * @param measureSpec the measure specification to extract the mode from
index dd32f85..89743e5 100644 (file)
@@ -5963,12 +5963,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
             } else if (childDimension == LayoutParams.MATCH_PARENT) {
                 // Child wants to be our size... find out how big it should
                 // be
-                resultSize = size;
+                resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                 resultMode = MeasureSpec.UNSPECIFIED;
             } else if (childDimension == LayoutParams.WRAP_CONTENT) {
                 // Child wants to determine its own size.... find out how
                 // big it should be
-                resultSize = size;
+                resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                 resultMode = MeasureSpec.UNSPECIFIED;
             }
             break;
index f06f3c2..11d7026 100644 (file)
@@ -662,7 +662,7 @@ class FastScroller {
 
         final int adjMaxWidth = maxWidth - marginLeft - marginRight;
         final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(adjMaxWidth, MeasureSpec.AT_MOST);
-        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(),
+        final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(),
                 MeasureSpec.UNSPECIFIED);
         view.measure(widthMeasureSpec, heightMeasureSpec);
 
@@ -702,7 +702,7 @@ class FastScroller {
         final int containerWidth = container.width();
         final int adjMaxWidth = containerWidth - marginLeft - marginRight;
         final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(adjMaxWidth, MeasureSpec.AT_MOST);
-        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(),
+        final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(),
                 MeasureSpec.UNSPECIFIED);
         preview.measure(widthMeasureSpec, heightMeasureSpec);
 
@@ -768,7 +768,7 @@ class FastScroller {
         final Rect container = mContainerRect;
         final int maxWidth = container.width();
         final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST);
-        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(),
+        final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(),
                 MeasureSpec.UNSPECIFIED);
         track.measure(widthMeasureSpec, heightMeasureSpec);
 
index dcaafa5..f994d4a 100644 (file)
@@ -1073,7 +1073,7 @@ public class GridView extends AbsListView {
             p.forceAdd = true;
 
             int childHeightSpec = getChildMeasureSpec(
-                    MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
+                    MeasureSpec.makeSafeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
                             MeasureSpec.UNSPECIFIED), 0, p.height);
             int childWidthSpec = getChildMeasureSpec(
                     MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
index 9d14254..056323d 100644 (file)
@@ -1062,9 +1062,9 @@ public class LinearLayout extends ViewGroup {
                 // use as much space as it wants because we can shrink things
                 // later (and re-measure).
                 if (baselineAligned) {
-                    final int freeWidthSpec = MeasureSpec.makeMeasureSpec(
+                    final int freeWidthSpec = MeasureSpec.makeSafeMeasureSpec(
                             MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.UNSPECIFIED);
-                    final int freeHeightSpec = MeasureSpec.makeMeasureSpec(
+                    final int freeHeightSpec = MeasureSpec.makeSafeMeasureSpec(
                             MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED);
                     child.measure(freeWidthSpec, freeHeightSpec);
                 } else {
index f8b965f..fd0395a 100644 (file)
@@ -1206,7 +1206,7 @@ public class ListView extends AbsListView {
         if (lpHeight > 0) {
             childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
         } else {
-            childHeightSpec = MeasureSpec.makeMeasureSpec(heightHint, MeasureSpec.UNSPECIFIED);
+            childHeightSpec = MeasureSpec.makeSafeMeasureSpec(heightHint, MeasureSpec.UNSPECIFIED);
         }
         child.measure(childWidthSpec, childHeightSpec);
     }
@@ -1943,7 +1943,7 @@ public class ListView extends AbsListView {
             if (lpHeight > 0) {
                 childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
             } else {
-                childHeightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(),
+                childHeightSpec = MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(),
                         MeasureSpec.UNSPECIFIED);
             }
             child.measure(childWidthSpec, childHeightSpec);
@@ -2698,7 +2698,7 @@ public class ListView extends AbsListView {
         if (lpHeight > 0) {
             childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
         } else {
-            childHeightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(),
+            childHeightSpec = MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(),
                     MeasureSpec.UNSPECIFIED);
         }
         child.measure(childWidthSpec, childHeightSpec);
index 11904e1..58a94b9 100644 (file)
@@ -1263,7 +1263,7 @@ public class ScrollView extends FrameLayout {
         childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft
                 + mPaddingRight, lp.width);
 
-        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+        childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(
                 MeasureSpec.getSize(parentHeightMeasureSpec), MeasureSpec.UNSPECIFIED);
 
         child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
@@ -1277,7 +1277,7 @@ public class ScrollView extends FrameLayout {
         final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                 mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
                         + widthUsed, lp.width);
-        final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+        final int childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(
                 MeasureSpec.getSize(parentHeightMeasureSpec), MeasureSpec.UNSPECIFIED);
 
         child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
index 6fe34dd..fdabe91 100644 (file)
@@ -812,9 +812,9 @@ public class Spinner extends AbsSpinner implements OnClickListener {
         View itemView = null;
         int itemType = 0;
         final int widthMeasureSpec =
-            MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.UNSPECIFIED);
+            MeasureSpec.makeSafeMeasureSpec(getMeasuredWidth(), MeasureSpec.UNSPECIFIED);
         final int heightMeasureSpec =
-            MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.UNSPECIFIED);
+            MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(), MeasureSpec.UNSPECIFIED);
 
         // Make sure the number of items we'll measure is capped. If it's a huge data set
         // with wildly varying sizes, oh well.
index aa7168c..d9cff4e 100644 (file)
@@ -174,7 +174,8 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
 
         // First, measure with no constraint
         final int width = MeasureSpec.getSize(widthMeasureSpec);
-        final int unspecifiedWidth = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
+        final int unspecifiedWidth = MeasureSpec.makeSafeMeasureSpec(width,
+                MeasureSpec.UNSPECIFIED);
         mImposedTabsHeight = -1;
         super.measureHorizontal(unspecifiedWidth, heightMeasureSpec);
 
index d4288d6..f7f9c91 100644 (file)
@@ -303,7 +303,7 @@ public class TableRow extends LinearLayout {
                             spec = getChildMeasureSpec(widthMeasureSpec, 0, LayoutParams.WRAP_CONTENT);
                             break;
                         case LayoutParams.MATCH_PARENT:
-                            spec = MeasureSpec.makeMeasureSpec(
+                            spec = MeasureSpec.makeSafeMeasureSpec(
                                     MeasureSpec.getSize(heightMeasureSpec),
                                     MeasureSpec.UNSPECIFIED);
                             break;
index 106272b..c5d3290 100644 (file)
@@ -367,7 +367,7 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
 
         if (mTitleLayout != null && mCustomView == null) {
             if (mTitleOptional) {
-                final int titleWidthSpec = MeasureSpec.makeMeasureSpec(contentWidth,
+                final int titleWidthSpec = MeasureSpec.makeSafeMeasureSpec(contentWidth,
                         MeasureSpec.UNSPECIFIED);
                 mTitleLayout.measure(titleWidthSpec, childSpecHeight);
                 final int titleWidth = mTitleLayout.getMeasuredWidth();
index 0066ed0..79adada 100644 (file)
@@ -403,10 +403,10 @@ public class SlidingTab extends ViewGroup {
         public void measure(int widthMeasureSpec, int heightMeasureSpec) {
             int width = MeasureSpec.getSize(widthMeasureSpec);
             int height = MeasureSpec.getSize(heightMeasureSpec);
-            tab.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
-                    View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
-            text.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
-                    View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
+            tab.measure(View.MeasureSpec.makeSafeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
+                    View.MeasureSpec.makeSafeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
+            text.measure(View.MeasureSpec.makeSafeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
+                    View.MeasureSpec.makeSafeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
         }
 
         /**