From f49d835dfe1bd21920ff8a48cbdfb9c1fd632fd9 Mon Sep 17 00:00:00 2001 From: Justin Ho Date: Wed, 17 Oct 2012 15:50:48 -0700 Subject: This restores JB MR0 behavior where the framework throws an exception for improper layouts that are missing layout_width and/or layout_height. This reverts commit 57fca90ac65ecfe97acd4c93d442c3db8f815e11 Change-Id: I0fe25056cd54b8852b32ae4621e048d3f5c7d555 --- api/current.txt | 4 +- core/java/android/content/res/TypedArray.java | 9 +-- core/java/android/view/LayoutInflater.java | 100 ++++++++++++++------------ core/java/android/view/ViewGroup.java | 10 +-- core/java/android/widget/FrameLayout.java | 6 -- core/java/android/widget/RadioGroup.java | 27 +++++++ core/java/android/widget/TableLayout.java | 9 ++- core/java/android/widget/TableRow.java | 15 +++- 8 files changed, 106 insertions(+), 74 deletions(-) diff --git a/api/current.txt b/api/current.txt index ee9a973..b5aa2c1 100644 --- a/api/current.txt +++ b/api/current.txt @@ -7094,7 +7094,7 @@ package android.content.res { method public int getIndexCount(); method public int getInt(int, int); method public int getInteger(int, int); - method public deprecated int getLayoutDimension(int, java.lang.String); + method public int getLayoutDimension(int, java.lang.String); method public int getLayoutDimension(int, int); method public java.lang.String getNonResourceString(int); method public java.lang.String getPositionDescription(); @@ -16149,7 +16149,7 @@ package android.os { public class Looper { method public void dump(android.util.Printer, java.lang.String); - method public static android.os.Looper getMainLooper(); + method public static synchronized android.os.Looper getMainLooper(); method public java.lang.Thread getThread(); method public static void loop(); method public static android.os.Looper myLooper(); diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java index 7f3b6b9..2968fbb 100644 --- a/core/java/android/content/res/TypedArray.java +++ b/core/java/android/content/res/TypedArray.java @@ -469,20 +469,13 @@ public class TypedArray { * {@link android.view.ViewGroup}'s layout_width and layout_height * attributes. This is only here for performance reasons; applications * should use {@link #getDimensionPixelSize}. - * + * * @param index Index of the attribute to retrieve. * @param name Textual name of attribute for error reporting. * * @return Attribute dimension value multiplied by the appropriate * metric and truncated to integer pixels. - * - * @throws RuntimeException - * if this TypedArray does not contain an entry for index - * - * @deprecated Use {@link #getLayoutDimension(int, int)} instead. - * */ - @Deprecated public int getLayoutDimension(int index, String name) { index *= AssetManager.STYLE_NUM_ENTRIES; final int[] data = mData; diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index f692e05..26a5b26 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -20,7 +20,6 @@ import android.graphics.Canvas; import android.os.Handler; import android.os.Message; import android.widget.FrameLayout; -import com.android.internal.R; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -44,20 +43,20 @@ import java.util.HashMap; * *
LayoutInflater inflater = (LayoutInflater)context.getSystemService
  *      (Context.LAYOUT_INFLATER_SERVICE);
- * + * *

* To create a new LayoutInflater with an additional {@link Factory} for your * own views, you can use {@link #cloneInContext} to clone an existing * ViewFactory, and then call {@link #setFactory} on it to include your * Factory. - * + * *

* For performance reasons, view inflation relies heavily on pre-processing of * XML files that is done at build time. Therefore, it is not currently possible * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime; * it only works with an XmlPullParser returned from a compiled resource * (R.something file.) - * + * * @see Context#getSystemService */ public abstract class LayoutInflater { @@ -83,7 +82,7 @@ public abstract class LayoutInflater { private static final HashMap> sConstructorMap = new HashMap>(); - + private HashMap mFilterMap; private static final String TAG_MERGE = "merge"; @@ -94,36 +93,36 @@ public abstract class LayoutInflater { /** * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed * to be inflated. - * + * */ public interface Filter { /** * Hook to allow clients of the LayoutInflater to restrict the set of Views * that are allowed to be inflated. - * + * * @param clazz The class object for the View that is about to be inflated - * + * * @return True if this class is allowed to be inflated, or false otherwise */ @SuppressWarnings("unchecked") boolean onLoadClass(Class clazz); } - + public interface Factory { /** * Hook you can supply that is called when inflating from a LayoutInflater. * You can use this to customize the tag names available in your XML * layout files. - * + * *

* Note that it is good practice to prefix these custom names with your * package (i.e., com.coolcompany.apps) to avoid conflicts with system * names. - * + * * @param name Tag name to be inflated. * @param context The context the view is being created in. * @param attrs Inflation attributes as specified in XML file. - * + * * @return View Newly created view. Return null for the default * behavior. */ @@ -151,14 +150,14 @@ public abstract class LayoutInflater { private static class FactoryMerger implements Factory2 { private final Factory mF1, mF2; private final Factory2 mF12, mF22; - + FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) { mF1 = f1; mF2 = f2; mF12 = f12; mF22 = f22; } - + public View onCreateView(String name, Context context, AttributeSet attrs) { View v = mF1.onCreateView(name, context, attrs); if (v != null) return v; @@ -173,13 +172,13 @@ public abstract class LayoutInflater { : mF2.onCreateView(name, context, attrs); } } - + /** * Create a new LayoutInflater instance associated with a particular Context. * Applications will almost always want to use * {@link Context#getSystemService Context.getSystemService()} to retrieve * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}. - * + * * @param context The Context in which this LayoutInflater will create its * Views; most importantly, this supplies the theme from which the default * values for their attributes are retrieved. @@ -192,7 +191,7 @@ public abstract class LayoutInflater { * Create a new LayoutInflater instance that is a copy of an existing * LayoutInflater, optionally with its Context changed. For use in * implementing {@link #cloneInContext}. - * + * * @param original The original LayoutInflater to copy. * @param newContext The new Context to use. */ @@ -203,7 +202,7 @@ public abstract class LayoutInflater { mPrivateFactory = original.mPrivateFactory; mFilter = original.mFilter; } - + /** * Obtains the LayoutInflater from the given context. */ @@ -221,15 +220,15 @@ public abstract class LayoutInflater { * pointing to a different Context than the original. This is used by * {@link ContextThemeWrapper} to create a new LayoutInflater to go along * with the new Context theme. - * + * * @param newContext The new Context to associate with the new LayoutInflater. * May be the same as the original Context if desired. - * + * * @return Returns a brand spanking new LayoutInflater object associated with * the given Context. */ public abstract LayoutInflater cloneInContext(Context newContext); - + /** * Return the context we are running in, for access to resources, class * loader, etc. @@ -265,7 +264,7 @@ public abstract class LayoutInflater { * called on each element name as the xml is parsed. If the factory returns * a View, that is added to the hierarchy. If it returns null, the next * factory default {@link #onCreateView} method is called. - * + * *

If you have an existing * LayoutInflater and want to add your own factory to it, use * {@link #cloneInContext} to clone the existing instance and then you @@ -321,13 +320,13 @@ public abstract class LayoutInflater { public Filter getFilter() { return mFilter; } - + /** * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will * throw an {@link InflateException}. This filter will replace any previous filter set on this * LayoutInflater. - * + * * @param filter The Filter which restricts the set of Views that are allowed to be inflated. * This filter will replace any previous filter set on this LayoutInflater. */ @@ -341,7 +340,7 @@ public abstract class LayoutInflater { /** * Inflate a new view hierarchy from the specified xml resource. Throws * {@link InflateException} if there is an error. - * + * * @param resource ID for an XML layout resource to load (e.g., * R.layout.main_page) * @param root Optional view to be the parent of the generated hierarchy. @@ -361,7 +360,7 @@ public abstract class LayoutInflater { * reasons, view inflation relies heavily on pre-processing of XML files * that is done at build time. Therefore, it is not currently possible to * use LayoutInflater with an XmlPullParser over a plain XML file at runtime. - * + * * @param parser XML dom node containing the description of the view * hierarchy. * @param root Optional view to be the parent of the generated hierarchy. @@ -376,7 +375,7 @@ public abstract class LayoutInflater { /** * Inflate a new view hierarchy from the specified xml resource. Throws * {@link InflateException} if there is an error. - * + * * @param resource ID for an XML layout resource to load (e.g., * R.layout.main_page) * @param root Optional view to be the parent of the generated hierarchy (if @@ -408,7 +407,7 @@ public abstract class LayoutInflater { * reasons, view inflation relies heavily on pre-processing of XML files * that is done at build time. Therefore, it is not currently possible to * use LayoutInflater with an XmlPullParser over a plain XML file at runtime. - * + * * @param parser XML dom node containing the description of the view * hierarchy. * @param root Optional view to be the parent of the generated hierarchy (if @@ -443,7 +442,7 @@ public abstract class LayoutInflater { } final String name = parser.getName(); - + if (DEBUG) { System.out.println("**************************"); System.out.println("Creating root view: " @@ -529,17 +528,17 @@ public abstract class LayoutInflater { * Low-level function for instantiating a view by name. This attempts to * instantiate a view class of the given name found in this * LayoutInflater's ClassLoader. - * + * *

* There are two things that can happen in an error case: either the * exception describing the error will be thrown, or a null will be * returned. You must deal with both possibilities -- the former will happen * the first time createView() is called for a class of a particular name, * the latter every time there-after for that class name. - * + * * @param name The full name of the class to be instantiated. * @param attrs The XML attributes supplied for this instance. - * + * * @return View The newly instantiated view, or null. */ public final View createView(String name, String prefix, AttributeSet attrs) @@ -552,7 +551,7 @@ public abstract class LayoutInflater { // Class not found in the cache, see if it's real, and try to add it clazz = mContext.getClassLoader().loadClass( prefix != null ? (prefix + name) : name).asSubclass(View.class); - + if (mFilter != null && clazz != null) { boolean allowed = mFilter.onLoadClass(clazz); if (!allowed) { @@ -570,7 +569,7 @@ public abstract class LayoutInflater { // New class -- remember whether it is allowed clazz = mContext.getClassLoader().loadClass( prefix != null ? (prefix + name) : name).asSubclass(View.class); - + boolean allowed = clazz != null && mFilter.onLoadClass(clazz); mFilterMap.put(name, allowed); if (!allowed) { @@ -633,10 +632,10 @@ public abstract class LayoutInflater { * given the xml element name. Override it to handle custom view objects. If * you override this in your subclass be sure to call through to * super.onCreateView(name) for names you do not recognize. - * + * * @param name The fully qualified class name of the View to be create. * @param attrs An AttributeSet of attributes to apply to the View. - * + * * @return View The View created. */ protected View onCreateView(String name, AttributeSet attrs) @@ -680,7 +679,7 @@ public abstract class LayoutInflater { if (view == null && mPrivateFactory != null) { view = mPrivateFactory.onCreateView(parent, name, mContext, attrs); } - + if (view == null) { if (-1 == name.indexOf('.')) { view = onCreateView(parent, name, attrs); @@ -727,7 +726,7 @@ public abstract class LayoutInflater { } final String name = parser.getName(); - + if (TAG_REQUEST_FOCUS.equals(name)) { parseRequestFocus(parser, parent); } else if (TAG_INCLUDE.equals(name)) { @@ -742,7 +741,7 @@ public abstract class LayoutInflater { final ViewGroup viewGroup = (ViewGroup) parent; final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs); rInflate(parser, view, attrs, true); - viewGroup.addView(view, params); + viewGroup.addView(view, params); } else { final View view = createViewFromTag(parent, name, attrs); final ViewGroup viewGroup = (ViewGroup) parent; @@ -811,14 +810,21 @@ public abstract class LayoutInflater { // We try to load the layout params set in the tag. If // they don't exist, we will rely on the layout params set in the // included XML file. - TypedArray ta = getContext().obtainStyledAttributes(attrs, - R.styleable.ViewGroup_Layout); - boolean definesBothWidthAndHeight = - ta.hasValue(R.styleable.ViewGroup_Layout_layout_width) && - ta.hasValue(R.styleable.ViewGroup_Layout_layout_height); - AttributeSet attributes = definesBothWidthAndHeight ? attrs : childAttrs; - view.setLayoutParams(group.generateLayoutParams(attributes)); - ta.recycle(); + // During a layoutparams generation, a runtime exception is thrown + // if either layout_width or layout_height is missing. We catch + // this exception and set localParams accordingly: true means we + // successfully loaded layout params from the tag, + // false means we need to rely on the included layout params. + ViewGroup.LayoutParams params = null; + try { + params = group.generateLayoutParams(attrs); + } catch (RuntimeException e) { + params = group.generateLayoutParams(childAttrs); + } finally { + if (params != null) { + view.setLayoutParams(params); + } + } // Inflate all children. rInflate(childParser, view, childAttrs, true); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 9ce7df9..6c1049b 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -5611,19 +5611,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** - * Extracts the width and height layout parameters - * from the supplied TypedArray, a, and assigns them - * to the appropriate fields. If, a, does not contain an - * entry for either attribute, the value, {@link ViewGroup.LayoutParams#WRAP_CONTENT}, - * is used as a default. + * Extracts the layout parameters from the supplied attributes. * * @param a the style attributes to extract the parameters from * @param widthAttr the identifier of the width attribute * @param heightAttr the identifier of the height attribute */ protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) { - width = a.getLayoutDimension(widthAttr, WRAP_CONTENT); - height = a.getLayoutDimension(heightAttr, WRAP_CONTENT); + width = a.getLayoutDimension(widthAttr, "layout_width"); + height = a.getLayoutDimension(heightAttr, "layout_height"); } /** diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index 45f30df..e158776 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -608,12 +608,6 @@ public class FrameLayout extends ViewGroup { */ public int gravity = -1; - @Override - protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) { - width = a.getLayoutDimension(widthAttr, MATCH_PARENT); - height = a.getLayoutDimension(heightAttr, MATCH_PARENT); - } - /** * {@inheritDoc} */ diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java index 42d63b2..78d05b0 100644 --- a/core/java/android/widget/RadioGroup.java +++ b/core/java/android/widget/RadioGroup.java @@ -297,6 +297,33 @@ public class RadioGroup extends LinearLayout { public LayoutParams(MarginLayoutParams source) { super(source); } + + /** + *

Fixes the child's width to + * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and the child's + * height to {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} + * when not specified in the XML file.

+ * + * @param a the styled attributes set + * @param widthAttr the width attribute to fetch + * @param heightAttr the height attribute to fetch + */ + @Override + protected void setBaseAttributes(TypedArray a, + int widthAttr, int heightAttr) { + + if (a.hasValue(widthAttr)) { + width = a.getLayoutDimension(widthAttr, "layout_width"); + } else { + width = WRAP_CONTENT; + } + + if (a.hasValue(heightAttr)) { + height = a.getLayoutDimension(heightAttr, "layout_height"); + } else { + height = WRAP_CONTENT; + } + } } /** diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java index 113299a..399b4fa 100644 --- a/core/java/android/widget/TableLayout.java +++ b/core/java/android/widget/TableLayout.java @@ -741,9 +741,14 @@ public class TableLayout extends LinearLayout { * @param heightAttr the height attribute to fetch */ @Override - protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) { + protected void setBaseAttributes(TypedArray a, + int widthAttr, int heightAttr) { this.width = MATCH_PARENT; - this.height = a.getLayoutDimension(heightAttr, WRAP_CONTENT); + if (a.hasValue(heightAttr)) { + this.height = a.getLayoutDimension(heightAttr, "layout_height"); + } else { + this.height = WRAP_CONTENT; + } } } diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java index 3f8f9dae..68ffd73 100644 --- a/core/java/android/widget/TableRow.java +++ b/core/java/android/widget/TableRow.java @@ -505,8 +505,19 @@ public class TableRow extends LinearLayout { @Override protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) { - width = a.getLayoutDimension(widthAttr, MATCH_PARENT); - height = a.getLayoutDimension(heightAttr, WRAP_CONTENT); + // We don't want to force users to specify a layout_width + if (a.hasValue(widthAttr)) { + width = a.getLayoutDimension(widthAttr, "layout_width"); + } else { + width = MATCH_PARENT; + } + + // We don't want to force users to specify a layout_height + if (a.hasValue(heightAttr)) { + height = a.getLayoutDimension(heightAttr, "layout_height"); + } else { + height = WRAP_CONTENT; + } } } -- cgit v1.1