2020import android .os .Handler ;
2121import android .os .Message ;
2222import android .widget .FrameLayout ;
23- import com .android .internal .R ;
2423import org .xmlpull .v1 .XmlPullParser ;
2524import org .xmlpull .v1 .XmlPullParserException ;
2625
4443 *
4544 * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
4645 * (Context.LAYOUT_INFLATER_SERVICE);</pre>
47- *
46+ *
4847 * <p>
4948 * To create a new LayoutInflater with an additional {@link Factory} for your
5049 * own views, you can use {@link #cloneInContext} to clone an existing
5150 * ViewFactory, and then call {@link #setFactory} on it to include your
5251 * Factory.
53- *
52+ *
5453 * <p>
5554 * For performance reasons, view inflation relies heavily on pre-processing of
5655 * XML files that is done at build time. Therefore, it is not currently possible
5756 * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
5857 * it only works with an XmlPullParser returned from a compiled resource
5958 * (R.<em>something</em> file.)
60- *
59+ *
6160 * @see Context#getSystemService
6261 */
6362public abstract class LayoutInflater {
@@ -83,7 +82,7 @@ public abstract class LayoutInflater {
8382
8483 private static final HashMap <String , Constructor <? extends View >> sConstructorMap =
8584 new HashMap <String , Constructor <? extends View >>();
86-
85+
8786 private HashMap <String , Boolean > mFilterMap ;
8887
8988 private static final String TAG_MERGE = "merge" ;
@@ -94,36 +93,36 @@ public abstract class LayoutInflater {
9493 /**
9594 * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
9695 * to be inflated.
97- *
96+ *
9897 */
9998 public interface Filter {
10099 /**
101100 * Hook to allow clients of the LayoutInflater to restrict the set of Views
102101 * that are allowed to be inflated.
103- *
102+ *
104103 * @param clazz The class object for the View that is about to be inflated
105- *
104+ *
106105 * @return True if this class is allowed to be inflated, or false otherwise
107106 */
108107 @ SuppressWarnings ("unchecked" )
109108 boolean onLoadClass (Class clazz );
110109 }
111-
110+
112111 public interface Factory {
113112 /**
114113 * Hook you can supply that is called when inflating from a LayoutInflater.
115114 * You can use this to customize the tag names available in your XML
116115 * layout files.
117- *
116+ *
118117 * <p>
119118 * Note that it is good practice to prefix these custom names with your
120119 * package (i.e., com.coolcompany.apps) to avoid conflicts with system
121120 * names.
122- *
121+ *
123122 * @param name Tag name to be inflated.
124123 * @param context The context the view is being created in.
125124 * @param attrs Inflation attributes as specified in XML file.
126- *
125+ *
127126 * @return View Newly created view. Return null for the default
128127 * behavior.
129128 */
@@ -151,14 +150,14 @@ public interface Factory2 extends Factory {
151150 private static class FactoryMerger implements Factory2 {
152151 private final Factory mF1 , mF2 ;
153152 private final Factory2 mF12 , mF22 ;
154-
153+
155154 FactoryMerger (Factory f1 , Factory2 f12 , Factory f2 , Factory2 f22 ) {
156155 mF1 = f1 ;
157156 mF2 = f2 ;
158157 mF12 = f12 ;
159158 mF22 = f22 ;
160159 }
161-
160+
162161 public View onCreateView (String name , Context context , AttributeSet attrs ) {
163162 View v = mF1 .onCreateView (name , context , attrs );
164163 if (v != null ) return v ;
@@ -173,13 +172,13 @@ public View onCreateView(View parent, String name, Context context, AttributeSet
173172 : mF2 .onCreateView (name , context , attrs );
174173 }
175174 }
176-
175+
177176 /**
178177 * Create a new LayoutInflater instance associated with a particular Context.
179178 * Applications will almost always want to use
180179 * {@link Context#getSystemService Context.getSystemService()} to retrieve
181180 * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
182- *
181+ *
183182 * @param context The Context in which this LayoutInflater will create its
184183 * Views; most importantly, this supplies the theme from which the default
185184 * values for their attributes are retrieved.
@@ -192,7 +191,7 @@ protected LayoutInflater(Context context) {
192191 * Create a new LayoutInflater instance that is a copy of an existing
193192 * LayoutInflater, optionally with its Context changed. For use in
194193 * implementing {@link #cloneInContext}.
195- *
194+ *
196195 * @param original The original LayoutInflater to copy.
197196 * @param newContext The new Context to use.
198197 */
@@ -203,7 +202,7 @@ protected LayoutInflater(LayoutInflater original, Context newContext) {
203202 mPrivateFactory = original .mPrivateFactory ;
204203 mFilter = original .mFilter ;
205204 }
206-
205+
207206 /**
208207 * Obtains the LayoutInflater from the given context.
209208 */
@@ -221,15 +220,15 @@ public static LayoutInflater from(Context context) {
221220 * pointing to a different Context than the original. This is used by
222221 * {@link ContextThemeWrapper} to create a new LayoutInflater to go along
223222 * with the new Context theme.
224- *
223+ *
225224 * @param newContext The new Context to associate with the new LayoutInflater.
226225 * May be the same as the original Context if desired.
227- *
226+ *
228227 * @return Returns a brand spanking new LayoutInflater object associated with
229228 * the given Context.
230229 */
231230 public abstract LayoutInflater cloneInContext (Context newContext );
232-
231+
233232 /**
234233 * Return the context we are running in, for access to resources, class
235234 * loader, etc.
@@ -265,7 +264,7 @@ public final Factory2 getFactory2() {
265264 * called on each element name as the xml is parsed. If the factory returns
266265 * a View, that is added to the hierarchy. If it returns null, the next
267266 * factory default {@link #onCreateView} method is called.
268- *
267+ *
269268 * <p>If you have an existing
270269 * LayoutInflater and want to add your own factory to it, use
271270 * {@link #cloneInContext} to clone the existing instance and then you
@@ -321,13 +320,13 @@ public void setPrivateFactory(Factory2 factory) {
321320 public Filter getFilter () {
322321 return mFilter ;
323322 }
324-
323+
325324 /**
326325 * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
327326 * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
328327 * throw an {@link InflateException}. This filter will replace any previous filter set on this
329328 * LayoutInflater.
330- *
329+ *
331330 * @param filter The Filter which restricts the set of Views that are allowed to be inflated.
332331 * This filter will replace any previous filter set on this LayoutInflater.
333332 */
@@ -341,7 +340,7 @@ public void setFilter(Filter filter) {
341340 /**
342341 * Inflate a new view hierarchy from the specified xml resource. Throws
343342 * {@link InflateException} if there is an error.
344- *
343+ *
345344 * @param resource ID for an XML layout resource to load (e.g.,
346345 * <code>R.layout.main_page</code>)
347346 * @param root Optional view to be the parent of the generated hierarchy.
@@ -361,7 +360,7 @@ public View inflate(int resource, ViewGroup root) {
361360 * reasons, view inflation relies heavily on pre-processing of XML files
362361 * that is done at build time. Therefore, it is not currently possible to
363362 * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
364- *
363+ *
365364 * @param parser XML dom node containing the description of the view
366365 * hierarchy.
367366 * @param root Optional view to be the parent of the generated hierarchy.
@@ -376,7 +375,7 @@ public View inflate(XmlPullParser parser, ViewGroup root) {
376375 /**
377376 * Inflate a new view hierarchy from the specified xml resource. Throws
378377 * {@link InflateException} if there is an error.
379- *
378+ *
380379 * @param resource ID for an XML layout resource to load (e.g.,
381380 * <code>R.layout.main_page</code>)
382381 * @param root Optional view to be the parent of the generated hierarchy (if
@@ -408,7 +407,7 @@ public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
408407 * reasons, view inflation relies heavily on pre-processing of XML files
409408 * that is done at build time. Therefore, it is not currently possible to
410409 * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
411- *
410+ *
412411 * @param parser XML dom node containing the description of the view
413412 * hierarchy.
414413 * @param root Optional view to be the parent of the generated hierarchy (if
@@ -443,7 +442,7 @@ public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)
443442 }
444443
445444 final String name = parser .getName ();
446-
445+
447446 if (DEBUG ) {
448447 System .out .println ("**************************" );
449448 System .out .println ("Creating root view: "
@@ -529,17 +528,17 @@ public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)
529528 * Low-level function for instantiating a view by name. This attempts to
530529 * instantiate a view class of the given <var>name</var> found in this
531530 * LayoutInflater's ClassLoader.
532- *
531+ *
533532 * <p>
534533 * There are two things that can happen in an error case: either the
535534 * exception describing the error will be thrown, or a null will be
536535 * returned. You must deal with both possibilities -- the former will happen
537536 * the first time createView() is called for a class of a particular name,
538537 * the latter every time there-after for that class name.
539- *
538+ *
540539 * @param name The full name of the class to be instantiated.
541540 * @param attrs The XML attributes supplied for this instance.
542- *
541+ *
543542 * @return View The newly instantiated view, or null.
544543 */
545544 public final View createView (String name , String prefix , AttributeSet attrs )
@@ -552,7 +551,7 @@ public final View createView(String name, String prefix, AttributeSet attrs)
552551 // Class not found in the cache, see if it's real, and try to add it
553552 clazz = mContext .getClassLoader ().loadClass (
554553 prefix != null ? (prefix + name ) : name ).asSubclass (View .class );
555-
554+
556555 if (mFilter != null && clazz != null ) {
557556 boolean allowed = mFilter .onLoadClass (clazz );
558557 if (!allowed ) {
@@ -570,7 +569,7 @@ public final View createView(String name, String prefix, AttributeSet attrs)
570569 // New class -- remember whether it is allowed
571570 clazz = mContext .getClassLoader ().loadClass (
572571 prefix != null ? (prefix + name ) : name ).asSubclass (View .class );
573-
572+
574573 boolean allowed = clazz != null && mFilter .onLoadClass (clazz );
575574 mFilterMap .put (name , allowed );
576575 if (!allowed ) {
@@ -633,10 +632,10 @@ private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
633632 * given the xml element name. Override it to handle custom view objects. If
634633 * you override this in your subclass be sure to call through to
635634 * super.onCreateView(name) for names you do not recognize.
636- *
635+ *
637636 * @param name The fully qualified class name of the View to be create.
638637 * @param attrs An AttributeSet of attributes to apply to the View.
639- *
638+ *
640639 * @return View The View created.
641640 */
642641 protected View onCreateView (String name , AttributeSet attrs )
@@ -680,7 +679,7 @@ View createViewFromTag(View parent, String name, AttributeSet attrs) {
680679 if (view == null && mPrivateFactory != null ) {
681680 view = mPrivateFactory .onCreateView (parent , name , mContext , attrs );
682681 }
683-
682+
684683 if (view == null ) {
685684 if (-1 == name .indexOf ('.' )) {
686685 view = onCreateView (parent , name , attrs );
@@ -727,7 +726,7 @@ void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs,
727726 }
728727
729728 final String name = parser .getName ();
730-
729+
731730 if (TAG_REQUEST_FOCUS .equals (name )) {
732731 parseRequestFocus (parser , parent );
733732 } else if (TAG_INCLUDE .equals (name )) {
@@ -742,7 +741,7 @@ void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs,
742741 final ViewGroup viewGroup = (ViewGroup ) parent ;
743742 final ViewGroup .LayoutParams params = viewGroup .generateLayoutParams (attrs );
744743 rInflate (parser , view , attrs , true );
745- viewGroup .addView (view , params );
744+ viewGroup .addView (view , params );
746745 } else {
747746 final View view = createViewFromTag (parent , name , attrs );
748747 final ViewGroup viewGroup = (ViewGroup ) parent ;
@@ -811,14 +810,21 @@ private void parseInclude(XmlPullParser parser, View parent, AttributeSet attrs)
811810 // We try to load the layout params set in the <include /> tag. If
812811 // they don't exist, we will rely on the layout params set in the
813812 // included XML file.
814- TypedArray ta = getContext ().obtainStyledAttributes (attrs ,
815- R .styleable .ViewGroup_Layout );
816- boolean definesBothWidthAndHeight =
817- ta .hasValue (R .styleable .ViewGroup_Layout_layout_width ) &&
818- ta .hasValue (R .styleable .ViewGroup_Layout_layout_height );
819- AttributeSet attributes = definesBothWidthAndHeight ? attrs : childAttrs ;
820- view .setLayoutParams (group .generateLayoutParams (attributes ));
821- ta .recycle ();
813+ // During a layoutparams generation, a runtime exception is thrown
814+ // if either layout_width or layout_height is missing. We catch
815+ // this exception and set localParams accordingly: true means we
816+ // successfully loaded layout params from the <include /> tag,
817+ // false means we need to rely on the included layout params.
818+ ViewGroup .LayoutParams params = null ;
819+ try {
820+ params = group .generateLayoutParams (attrs );
821+ } catch (RuntimeException e ) {
822+ params = group .generateLayoutParams (childAttrs );
823+ } finally {
824+ if (params != null ) {
825+ view .setLayoutParams (params );
826+ }
827+ }
822828
823829 // Inflate all children.
824830 rInflate (childParser , view , childAttrs , true );
0 commit comments