19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.view;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viveretteimport com.android.internal.R;
200810b63739c9981f993063749f804b54faed0ba5Alan Viverette
213030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport org.xmlpull.v1.XmlPullParser;
223030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport org.xmlpull.v1.XmlPullParserException;
233030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne
247b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbyeimport android.annotation.LayoutRes;
25e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viveretteimport android.annotation.Nullable;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
270810b63739c9981f993063749f804b54faed0ba5Alan Viveretteimport android.content.res.Resources;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.XmlResourceParser;
30e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viveretteimport android.graphics.Canvas;
31e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viveretteimport android.os.Handler;
32e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viveretteimport android.os.Message;
33e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viveretteimport android.os.Trace;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
350810b63739c9981f993063749f804b54faed0ba5Alan Viveretteimport android.util.Log;
36e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viveretteimport android.util.TypedValue;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Xml;
38e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viveretteimport android.widget.FrameLayout;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Constructor;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
4593dc642eaf48e3db58c4929df26283fbc5fd663fScott Main * Instantiates a layout XML file into its corresponding {@link android.view.View}
4693dc642eaf48e3db58c4929df26283fbc5fd663fScott Main * objects. It is never used directly. Instead, use
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.app.Activity#getLayoutInflater()} or
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Context#getSystemService} to retrieve a standard LayoutInflater instance
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that is already hooked up to the current context and correctly configured
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for the device you are running on.  For example:
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
53bd6fda11d287ba8ac749e06053dc9488653d1471Christian Mehlmauer *      (Context.LAYOUT_INFLATER_SERVICE);</pre>
54579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke *
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To create a new LayoutInflater with an additional {@link Factory} for your
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * own views, you can use {@link #cloneInContext} to clone an existing
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ViewFactory, and then call {@link #setFactory} on it to include your
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Factory.
60579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke *
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For performance reasons, view inflation relies heavily on pre-processing of
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * XML files that is done at build time. Therefore, it is not currently possible
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it only works with an XmlPullParser returned from a compiled resource
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (R.<em>something</em> file.)
67579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke *
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see Context#getSystemService
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class LayoutInflater {
7133e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette
720810b63739c9981f993063749f804b54faed0ba5Alan Viverette    private static final String TAG = LayoutInflater.class.getSimpleName();
730810b63739c9981f993063749f804b54faed0ba5Alan Viverette    private static final boolean DEBUG = false;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
758f124818025564d67bc835067c224df32254e97bAlan Viverette    /** Empty stack trace used to avoid log spam in re-throw exceptions. */
768f124818025564d67bc835067c224df32254e97bAlan Viverette    private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
778f124818025564d67bc835067c224df32254e97bAlan Viverette
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This field should be made private, so it is hidden from the SDK.
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected final Context mContext;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these are optional, set by the caller
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mFactorySet;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Factory mFactory;
87625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    private Factory2 mFactory2;
88420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    private Factory2 mPrivateFactory;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Filter mFilter;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
917f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    final Object[] mConstructorArgs = new Object[2];
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
937f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    static final Class<?>[] mConstructorSignature = new Class[] {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Context.class, AttributeSet.class};
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
963030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne    private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
973030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            new HashMap<String, Constructor<? extends View>>();
98579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String, Boolean> mFilterMap;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10133e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette    private TypedValue mTempValue;
10233e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_MERGE = "merge";
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_INCLUDE = "include";
1059c1223a71397b565f38015c07cae57a5015a6500Romain Guy    private static final String TAG_1995 = "blink";
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_REQUEST_FOCUS = "requestFocus";
107451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    private static final String TAG_TAG = "tag";
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10933e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette    private static final String ATTR_LAYOUT = "layout";
11033e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette
111ef259e4484deb69ada76970e26f2b2542b1fe4c1Alan Viverette    private static final int[] ATTRS_THEME = new int[] {
112ef259e4484deb69ada76970e26f2b2542b1fe4c1Alan Viverette            com.android.internal.R.attr.theme };
11324927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to be inflated.
117579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Filter {
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Hook to allow clients of the LayoutInflater to restrict the set of Views
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * that are allowed to be inflated.
123579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param clazz The class object for the View that is about to be inflated
125579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return True if this class is allowed to be inflated, or false otherwise
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
128e6ac8b9aade9443ab8456c8f7a47cdfba3b70266Gilles Debunne        @SuppressWarnings("unchecked")
129e6ac8b9aade9443ab8456c8f7a47cdfba3b70266Gilles Debunne        boolean onLoadClass(Class clazz);
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
131579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Factory {
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Hook you can supply that is called when inflating from a LayoutInflater.
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * You can use this to customize the tag names available in your XML
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * layout files.
137579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note that it is good practice to prefix these custom names with your
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * package (i.e., com.coolcompany.apps) to avoid conflicts with system
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * names.
142579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param name Tag name to be inflated.
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param context The context the view is being created in.
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param attrs Inflation attributes as specified in XML file.
146579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return View Newly created view. Return null for the default
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *         behavior.
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View onCreateView(String name, Context context, AttributeSet attrs);
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
153625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public interface Factory2 extends Factory {
154625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        /**
155625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * Version of {@link #onCreateView(String, Context, AttributeSet)}
156625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * that also supplies the parent that the view created view will be
157625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * placed in.
158625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *
159625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param parent The parent that the created view will be placed
160625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * in; <em>note that this may be null</em>.
161625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param name Tag name to be inflated.
162625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param context The context the view is being created in.
163625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param attrs Inflation attributes as specified in XML file.
164625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *
165625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @return View Newly created view. Return null for the default
166625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *         behavior.
167625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         */
168625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        public View onCreateView(View parent, String name, Context context, AttributeSet attrs);
169625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
170625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
171625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    private static class FactoryMerger implements Factory2 {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final Factory mF1, mF2;
173625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        private final Factory2 mF12, mF22;
174579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
175625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mF1 = f1;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mF2 = f2;
178625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mF12 = f12;
179625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mF22 = f22;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
181579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View onCreateView(String name, Context context, AttributeSet attrs) {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View v = mF1.onCreateView(name, context, attrs);
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (v != null) return v;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mF2.onCreateView(name, context, attrs);
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
187625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
188625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
189625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            View v = mF12 != null ? mF12.onCreateView(parent, name, context, attrs)
190625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                    : mF1.onCreateView(name, context, attrs);
191625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            if (v != null) return v;
192625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            return mF22 != null ? mF22.onCreateView(parent, name, context, attrs)
193625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                    : mF2.onCreateView(name, context, attrs);
194625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
196579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new LayoutInflater instance associated with a particular Context.
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Applications will almost always want to use
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link Context#getSystemService Context.getSystemService()} to retrieve
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
202579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context The Context in which this LayoutInflater will create its
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Views; most importantly, this supplies the theme from which the default
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * values for their attributes are retrieved.
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected LayoutInflater(Context context) {
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new LayoutInflater instance that is a copy of an existing
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater, optionally with its Context changed.  For use in
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementing {@link #cloneInContext}.
215579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param original The original LayoutInflater to copy.
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param newContext The new Context to use.
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected LayoutInflater(LayoutInflater original, Context newContext) {
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = newContext;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFactory = original.mFactory;
222625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        mFactory2 = original.mFactory2;
223420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn        mPrivateFactory = original.mPrivateFactory;
2240c7bb33e03392416fc98c27738d1bcca386a6b2fDan Sandler        setFilter(original.mFilter);
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
226579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Obtains the LayoutInflater from the given context.
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static LayoutInflater from(Context context) {
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LayoutInflater LayoutInflater =
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LayoutInflater == null) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new AssertionError("LayoutInflater not found.");
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return LayoutInflater;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a copy of the existing LayoutInflater object, with the copy
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pointing to a different Context than the original.  This is used by
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ContextThemeWrapper} to create a new LayoutInflater to go along
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with the new Context theme.
244579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param newContext The new Context to associate with the new LayoutInflater.
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * May be the same as the original Context if desired.
247579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a brand spanking new LayoutInflater object associated with
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the given Context.
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract LayoutInflater cloneInContext(Context newContext);
252579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the context we are running in, for access to resources, class
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * loader, etc.
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Context getContext() {
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContext;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
262625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Return the current {@link Factory} (or null). This is called on each element
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * name. If the factory returns a View, add that to the hierarchy. If it
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returns null, proceed to call onCreateView(name).
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final Factory getFactory() {
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFactory;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
271625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Return the current {@link Factory2}.  Returns null if no factory is set
272625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * or the set factory does not implement the {@link Factory2} interface.
273625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * This is called on each element
274625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * name. If the factory returns a View, add that to the hierarchy. If it
275625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * returns null, proceed to call onCreateView(name).
276625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
277625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public final Factory2 getFactory2() {
278625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        return mFactory2;
279625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
280625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
281625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Attach a custom Factory interface for creating views while using
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this LayoutInflater.  This must not be null, and can only be set once;
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after setting, you can not change the factory.  This is
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called on each element name as the xml is parsed. If the factory returns
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a View, that is added to the hierarchy. If it returns null, the next
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * factory default {@link #onCreateView} method is called.
288579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If you have an existing
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater and want to add your own factory to it, use
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #cloneInContext} to clone the existing instance and then you
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can use this function (once) on the returned new instance.  This will
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * merge your own factory with whatever factory the original instance is
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * using.
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFactory(Factory factory) {
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFactorySet) {
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (factory == null) {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new NullPointerException("Given factory can not be null");
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFactorySet = true;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFactory == null) {
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFactory = factory;
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
307625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mFactory = new FactoryMerger(factory, null, mFactory, mFactory2);
308625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
309625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
310625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
311625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
312625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Like {@link #setFactory}, but allows you to set a {@link Factory2}
313625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * interface.
314625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
315625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public void setFactory2(Factory2 factory) {
316625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (mFactorySet) {
317625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
318625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
319625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (factory == null) {
320625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throw new NullPointerException("Given factory can not be null");
321625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
322625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        mFactorySet = true;
323625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (mFactory == null) {
324625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mFactory = mFactory2 = factory;
325625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        } else {
326371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell            mFactory = mFactory2 = new FactoryMerger(factory, factory, mFactory, mFactory2);
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
331420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn     * @hide for use by framework
332420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn     */
333420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    public void setPrivateFactory(Factory2 factory) {
334371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell        if (mPrivateFactory == null) {
335371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell            mPrivateFactory = factory;
336371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell        } else {
337371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell            mPrivateFactory = new FactoryMerger(factory, factory, mPrivateFactory, mPrivateFactory);
338371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell        }
339420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    }
340420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn
341420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    /**
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The {@link Filter} currently used by this LayoutInflater to restrict the set of Views
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that are allowed to be inflated.
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Filter getFilter() {
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFilter;
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
348579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * throw an {@link InflateException}. This filter will replace any previous filter set on this
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater.
354579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param filter The Filter which restricts the set of Views that are allowed to be inflated.
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        This filter will replace any previous filter set on this LayoutInflater.
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFilter(Filter filter) {
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilter = filter;
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (filter != null) {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFilterMap = new HashMap<String, Boolean>();
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml resource. Throws
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
368579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resource ID for an XML layout resource to load (e.g.,
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <code>R.layout.main_page</code>)
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy.
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied,
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         this is the root View; otherwise it is the root of the inflated
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         XML file.
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3767b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye    public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return inflate(resource, root, root != null);
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml node. Throws
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error. *
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * reasons, view inflation relies heavily on pre-processing of XML files
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that is done at build time. Therefore, it is not currently possible to
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
388579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parser XML dom node containing the description of the view
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy.
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy.
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied,
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         this is the root View; otherwise it is the root of the inflated
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         XML file.
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
396db5fd42a03b35c9a6d4ddb3ac9c239911af6d29fScott Kennedy    public View inflate(XmlPullParser parser, @Nullable ViewGroup root) {
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return inflate(parser, root, root != null);
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml resource. Throws
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
403579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resource ID for an XML layout resource to load (e.g.,
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <code>R.layout.main_page</code>)
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy (if
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <em>attachToRoot</em> is true), or else simply an object that
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        provides a set of LayoutParams values for root of the returned
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy (if <em>attachToRoot</em> is false.)
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attachToRoot Whether the inflated hierarchy should be attached to
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        the root parameter? If false, root is only used to create the
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        correct subclass of LayoutParams for the root view in the XML.
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied and
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         attachToRoot is true, this is root; otherwise it is the root of
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the inflated XML file.
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4177b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye    public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
4180810b63739c9981f993063749f804b54faed0ba5Alan Viverette        final Resources res = getContext().getResources();
4190810b63739c9981f993063749f804b54faed0ba5Alan Viverette        if (DEBUG) {
4200810b63739c9981f993063749f804b54faed0ba5Alan Viverette            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
4210810b63739c9981f993063749f804b54faed0ba5Alan Viverette                    + Integer.toHexString(resource) + ")");
4220810b63739c9981f993063749f804b54faed0ba5Alan Viverette        }
4230810b63739c9981f993063749f804b54faed0ba5Alan Viverette
4240810b63739c9981f993063749f804b54faed0ba5Alan Viverette        final XmlResourceParser parser = res.getLayout(resource);
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return inflate(parser, root, attachToRoot);
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            parser.close();
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified XML node. Throws
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * reasons, view inflation relies heavily on pre-processing of XML files
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that is done at build time. Therefore, it is not currently possible to
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
440579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parser XML dom node containing the description of the view
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy.
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy (if
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <em>attachToRoot</em> is true), or else simply an object that
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        provides a set of LayoutParams values for root of the returned
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy (if <em>attachToRoot</em> is false.)
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attachToRoot Whether the inflated hierarchy should be attached to
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        the root parameter? If false, root is only used to create the
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        correct subclass of LayoutParams for the root view in the XML.
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied and
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         attachToRoot is true, this is root; otherwise it is the root of
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the inflated XML file.
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
454db5fd42a03b35c9a6d4ddb3ac9c239911af6d29fScott Kennedy    public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mConstructorArgs) {
45609f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");
45709f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy
4586194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            final Context inflaterContext = mContext;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final AttributeSet attrs = Xml.asAttributeSet(parser);
4606194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            Context lastContext = (Context) mConstructorArgs[0];
4616194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            mConstructorArgs[0] = inflaterContext;
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View result = root;
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Look for the root node.
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int type;
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while ((type = parser.next()) != XmlPullParser.START_TAG &&
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        type != XmlPullParser.END_DOCUMENT) {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Empty
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type != XmlPullParser.START_TAG) {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException(parser.getPositionDescription()
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + ": No start tag found!");
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final String name = parser.getName();
478579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) {
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("**************************");
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("Creating root view: "
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + name);
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("**************************");
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (TAG_MERGE.equals(name)) {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root == null || !attachToRoot) {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        throw new InflateException("<merge /> can be used only with a valid "
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                + "ViewGroup root and attachToRoot=true");
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4926194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                    rInflate(parser, root, inflaterContext, attrs, false);
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Temp is the root view that was found in the xml
4956194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ViewGroup.LayoutParams params = null;
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root != null) {
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (DEBUG) {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.out.println("Creating params from root: " +
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    root);
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Create layout params that match root, if supplied
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        params = root.generateLayoutParams(attrs);
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!attachToRoot) {
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // Set the layout params for temp if we are not
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // attaching. (If we are, we use addView, below)
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            temp.setLayoutParams(params);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (DEBUG) {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        System.out.println("-----> start inflating children");
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5166194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette
5176194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                    // Inflate all children under temp against its context.
5186194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                    rInflateChildren(parser, temp, attrs, true);
5196194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (DEBUG) {
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        System.out.println("-----> done inflating children");
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We are supposed to attach all the views we found (int temp)
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to root. Do that now.
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root != null && attachToRoot) {
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        root.addView(temp, params);
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Decide whether to return the root that was passed in or the
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // top view found in xml.
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root == null || !attachToRoot) {
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        result = temp;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (XmlPullParserException e) {
5388f124818025564d67bc835067c224df32254e97bAlan Viverette                final InflateException ie = new InflateException(e.getMessage(), e);
5398f124818025564d67bc835067c224df32254e97bAlan Viverette                ie.setStackTrace(EMPTY_STACK_TRACE);
5408f124818025564d67bc835067c224df32254e97bAlan Viverette                throw ie;
54193795053da04b0f16dadb6e56f6056bd2dd37875Alan Viverette            } catch (Exception e) {
5428f124818025564d67bc835067c224df32254e97bAlan Viverette                final InflateException ie = new InflateException(parser.getPositionDescription()
5438f124818025564d67bc835067c224df32254e97bAlan Viverette                        + ": " + e.getMessage(), e);
5448f124818025564d67bc835067c224df32254e97bAlan Viverette                ie.setStackTrace(EMPTY_STACK_TRACE);
5458f124818025564d67bc835067c224df32254e97bAlan Viverette                throw ie;
5469dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn            } finally {
5479dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                // Don't retain static reference on context.
5489dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                mConstructorArgs[0] = lastContext;
5499dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                mConstructorArgs[1] = null;
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
551465e1a3e12d1c420af150e54ca78844c5964281cJohn Reck                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
552465e1a3e12d1c420af150e54ca78844c5964281cJohn Reck            }
55309f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return result;
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5584985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood    private static final ClassLoader BOOT_CLASS_LOADER = LayoutInflater.class.getClassLoader();
5594985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood
5604985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood    private final boolean verifyClassLoader(Constructor<? extends View> constructor) {
5614985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood        final ClassLoader constructorLoader = constructor.getDeclaringClass().getClassLoader();
5624985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood        if (constructorLoader == BOOT_CLASS_LOADER) {
5634985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood            // fast path for boot class loader (most common case?) - always ok
5644985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood            return true;
5654985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood        }
5664985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood        // in all normal cases (no dynamic code loading), we will exit the following loop on the
5674985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood        // first iteration (i.e. when the declaring classloader is the contexts class loader).
5684985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood        ClassLoader cl = mContext.getClassLoader();
5694985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood        do {
5704985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood            if (constructorLoader == cl) {
5714985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood                return true;
5724985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood            }
5734985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood            cl = cl.getParent();
5744985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood        } while (cl != null);
5754985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood        return false;
5764985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood    }
5774985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Low-level function for instantiating a view by name. This attempts to
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instantiate a view class of the given <var>name</var> found in this
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater's ClassLoader.
582579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * There are two things that can happen in an error case: either the
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * exception describing the error will be thrown, or a null will be
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned. You must deal with both possibilities -- the former will happen
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the first time createView() is called for a class of a particular name,
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the latter every time there-after for that class name.
589579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param name The full name of the class to be instantiated.
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attrs The XML attributes supplied for this instance.
592579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
5933030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne     * @return View The newly instantiated view, or null.
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final View createView(String name, String prefix, AttributeSet attrs)
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ClassNotFoundException, InflateException {
5973030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        Constructor<? extends View> constructor = sConstructorMap.get(name);
5984985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood        if (constructor != null && !verifyClassLoader(constructor)) {
5994985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood            constructor = null;
6004985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood            sConstructorMap.remove(name);
6014985c5c782661c2fd0ae6c368062b5203222c087Mathew Inwood        }
6023030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        Class<? extends View> clazz = null;
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
60509f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy            Trace.traceBegin(Trace.TRACE_TAG_VIEW, name);
60609f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (constructor == null) {
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Class not found in the cache, see if it's real, and try to add it
609d03b880836bcc4fae83a95458e0709cd45aa6313Romain Guy                clazz = mContext.getClassLoader().loadClass(
6103030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                        prefix != null ? (prefix + name) : name).asSubclass(View.class);
611579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFilter != null && clazz != null) {
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean allowed = mFilter.onLoadClass(clazz);
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!allowed) {
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        failNotAllowed(name, prefix, attrs);
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                constructor = clazz.getConstructor(mConstructorSignature);
619904de2ec9360de2ee54b91aaf9e141d9d8ab1de1Alan Viverette                constructor.setAccessible(true);
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sConstructorMap.put(name, constructor);
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If we have a filter, apply it to cached constructor
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFilter != null) {
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Have we seen this name before?
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Boolean allowedState = mFilterMap.get(name);
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (allowedState == null) {
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // New class -- remember whether it is allowed
628d03b880836bcc4fae83a95458e0709cd45aa6313Romain Guy                        clazz = mContext.getClassLoader().loadClass(
6293030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                                prefix != null ? (prefix + name) : name).asSubclass(View.class);
630579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mFilterMap.put(name, allowed);
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!allowed) {
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            failNotAllowed(name, prefix, attrs);
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (allowedState.equals(Boolean.FALSE)) {
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        failNotAllowed(name, prefix, attrs);
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Object[] args = mConstructorArgs;
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            args[1] = attrs;
644b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey
645b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            final View view = constructor.newInstance(args);
646b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            if (view instanceof ViewStub) {
647a9ddb8dc23b253c53f24ceb81e9d596c072d834eAlan Viverette                // Use the same context when inflating ViewStub later.
648b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey                final ViewStub viewStub = (ViewStub) view;
649a9ddb8dc23b253c53f24ceb81e9d596c072d834eAlan Viverette                viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
650b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            }
651b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            return view;
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (NoSuchMethodException e) {
6548f124818025564d67bc835067c224df32254e97bAlan Viverette            final InflateException ie = new InflateException(attrs.getPositionDescription()
6558f124818025564d67bc835067c224df32254e97bAlan Viverette                    + ": Error inflating class " + (prefix != null ? (prefix + name) : name), e);
6568f124818025564d67bc835067c224df32254e97bAlan Viverette            ie.setStackTrace(EMPTY_STACK_TRACE);
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6593030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        } catch (ClassCastException e) {
6603030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            // If loaded class is not a View subclass
6618f124818025564d67bc835067c224df32254e97bAlan Viverette            final InflateException ie = new InflateException(attrs.getPositionDescription()
6628f124818025564d67bc835067c224df32254e97bAlan Viverette                    + ": Class is not a View " + (prefix != null ? (prefix + name) : name), e);
6638f124818025564d67bc835067c224df32254e97bAlan Viverette            ie.setStackTrace(EMPTY_STACK_TRACE);
6643030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            throw ie;
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (ClassNotFoundException e) {
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If loadClass fails, we should propagate the exception.
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
6698f124818025564d67bc835067c224df32254e97bAlan Viverette            final InflateException ie = new InflateException(
6708f124818025564d67bc835067c224df32254e97bAlan Viverette                    attrs.getPositionDescription() + ": Error inflating class "
6718f124818025564d67bc835067c224df32254e97bAlan Viverette                            + (clazz == null ? "<unknown>" : clazz.getName()), e);
6728f124818025564d67bc835067c224df32254e97bAlan Viverette            ie.setStackTrace(EMPTY_STACK_TRACE);
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
67409f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy        } finally {
67509f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6803030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne     * Throw an exception because the specified class is not allowed to be inflated.
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
6839c1223a71397b565f38015c07cae57a5015a6500Romain Guy        throw new InflateException(attrs.getPositionDescription()
6848f124818025564d67bc835067c224df32254e97bAlan Viverette                + ": Class not allowed to be inflated "+ (prefix != null ? (prefix + name) : name));
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This routine is responsible for creating the correct subclass of View
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * given the xml element name. Override it to handle custom view objects. If
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * you override this in your subclass be sure to call through to
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * super.onCreateView(name) for names you do not recognize.
692579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param name The fully qualified class name of the View to be create.
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attrs An AttributeSet of attributes to apply to the View.
695579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return View The View created.
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected View onCreateView(String name, AttributeSet attrs)
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ClassNotFoundException {
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return createView(name, "android.view.", attrs);
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
703625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
704625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Version of {@link #onCreateView(String, AttributeSet)} that also
705430742f09063574271e6c4091de13b9b9e762514Chet Haase     * takes the future parent of the view being constructed.  The default
706625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * implementation simply calls {@link #onCreateView(String, AttributeSet)}.
707625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     *
708625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param parent The future parent of the returned view.  <em>Note that
709625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * this may be null.</em>
710625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param name The fully qualified class name of the View to be create.
711625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param attrs An AttributeSet of attributes to apply to the View.
712625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     *
713625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @return View The View created.
714625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
715625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    protected View onCreateView(View parent, String name, AttributeSet attrs)
716625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throws ClassNotFoundException {
717625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        return onCreateView(name, attrs);
718625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
719625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
72024927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette    /**
7216194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * Convenience method for calling through to the five-arg createViewFromTag
7226194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * method. This method passes {@code false} for the {@code ignoreThemeAttr}
7236194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * argument and should be used for everything except {@code &gt;include>}
7246194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * tag parsing.
7256194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     */
7266194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    private View createViewFromTag(View parent, String name, Context context, AttributeSet attrs) {
7276194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        return createViewFromTag(parent, name, context, attrs, false);
7286194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    }
7296194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette
7306194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    /**
73124927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     * Creates a view from a tag name using the supplied attribute set.
73224927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     * <p>
7336194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * <strong>Note:</strong> Default visibility so the BridgeInflater can
7346194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * override it.
7356194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     *
7366194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * @param parent the parent view, used to inflate layout params
7376194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * @param name the name of the XML tag used to define the view
7386194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * @param context the inflation context for the view, typically the
7396194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     *                {@code parent} or base layout inflater context
7406194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * @param attrs the attribute set for the XML tag used to define the view
7416194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * @param ignoreThemeAttr {@code true} to ignore the {@code android:theme}
7426194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     *                        attribute (if set) for the view being inflated,
7436194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     *                        {@code false} otherwise
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7456194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
7466194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            boolean ignoreThemeAttr) {
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (name.equals("view")) {
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            name = attrs.getAttributeValue(null, "class");
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7516194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        // Apply a theme wrapper, if allowed and one is specified.
7526194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        if (!ignoreThemeAttr) {
7536194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
7546194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            final int themeResId = ta.getResourceId(0, 0);
7556194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            if (themeResId != 0) {
7566194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                context = new ContextThemeWrapper(context, themeResId);
7576194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            }
7586194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            ta.recycle();
75924927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        }
76024927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette
76124927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        if (name.equals(TAG_1995)) {
76224927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            // Let's party like it's 1995!
7636194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            return new BlinkLayout(context, attrs);
76424927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        }
76524927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
767625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            View view;
76824927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            if (mFactory2 != null) {
7696194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                view = mFactory2.onCreateView(parent, name, context, attrs);
77024927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            } else if (mFactory != null) {
7716194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                view = mFactory.onCreateView(name, context, attrs);
77224927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            } else {
77324927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                view = null;
77424927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            }
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
776420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn            if (view == null && mPrivateFactory != null) {
7776194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                view = mPrivateFactory.onCreateView(parent, name, context, attrs);
778420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn            }
77924927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (view == null) {
78124927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                final Object lastContext = mConstructorArgs[0];
7826194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                mConstructorArgs[0] = context;
78324927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                try {
78424927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                    if (-1 == name.indexOf('.')) {
78524927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                        view = onCreateView(parent, name, attrs);
78624927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                    } else {
78724927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                        view = createView(name, null, attrs);
78824927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                    }
78924927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                } finally {
79024927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                    mConstructorArgs[0] = lastContext;
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return view;
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (InflateException e) {
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (ClassNotFoundException e) {
7996194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            final InflateException ie = new InflateException(attrs.getPositionDescription()
8008f124818025564d67bc835067c224df32254e97bAlan Viverette                    + ": Error inflating class " + name, e);
8018f124818025564d67bc835067c224df32254e97bAlan Viverette            ie.setStackTrace(EMPTY_STACK_TRACE);
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
8056194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            final InflateException ie = new InflateException(attrs.getPositionDescription()
8068f124818025564d67bc835067c224df32254e97bAlan Viverette                    + ": Error inflating class " + name, e);
8078f124818025564d67bc835067c224df32254e97bAlan Viverette            ie.setStackTrace(EMPTY_STACK_TRACE);
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8136194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * Recursive method used to inflate internal (non-root) children. This
8146194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * method calls through to {@link #rInflate} using the parent context as
8156194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * the inflation context.
8166194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * <strong>Note:</strong> Default visibility so the BridgeInflater can
8176194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * call it.
8186194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     */
8196194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    final void rInflateChildren(XmlPullParser parser, View parent, AttributeSet attrs,
8206194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            boolean finishInflate) throws XmlPullParserException, IOException {
8216194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        rInflate(parser, parent, parent.getContext(), attrs, finishInflate);
8226194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    }
8236194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette
8246194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    /**
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Recursive method used to descend down the xml hierarchy and instantiate
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * views, instantiate their children, and then call onFinishInflate().
8276194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * <p>
8286194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * <strong>Note:</strong> Default visibility so the BridgeInflater can
8296194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * override it.
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8316194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    void rInflate(XmlPullParser parser, View parent, Context context,
8326194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int depth = parser.getDepth();
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (((type = parser.next()) != XmlPullParser.END_TAG ||
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type != XmlPullParser.START_TAG) {
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String name = parser.getName();
845579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (TAG_REQUEST_FOCUS.equals(name)) {
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parseRequestFocus(parser, parent);
848451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette            } else if (TAG_TAG.equals(name)) {
849451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette                parseViewTag(parser, parent, attrs);
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (TAG_INCLUDE.equals(name)) {
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (parser.getDepth() == 0) {
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException("<include /> cannot be the root element");
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8546194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                parseInclude(parser, context, parent, attrs);
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (TAG_MERGE.equals(name)) {
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new InflateException("<merge /> must be the root element");
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8586194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                final View view = createViewFromTag(parent, name, context, attrs);
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ViewGroup viewGroup = (ViewGroup) parent;
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
8616194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                rInflateChildren(parser, view, attrs, true);
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                viewGroup.addView(view, params);
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8666194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        if (finishInflate) {
8676194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            parent.onFinishInflate();
8686194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        }
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
871451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    /**
872451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     * Parses a <code>&lt;request-focus&gt;</code> element and requests focus on
873451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     * the containing View.
874451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     */
875451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    private void parseRequestFocus(XmlPullParser parser, View view)
876451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette            throws XmlPullParserException, IOException {
877451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        view.requestFocus();
8786194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette
8796194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        consumeChildElements(parser);
880451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    }
881451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette
882451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    /**
883451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     * Parses a <code>&lt;tag&gt;</code> element and sets a keyed tag on the
884451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     * containing View.
885451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     */
886451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    private void parseViewTag(XmlPullParser parser, View view, AttributeSet attrs)
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
8886194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        final Context context = view.getContext();
8896194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ViewTag);
8906194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        final int key = ta.getResourceId(R.styleable.ViewTag_id, 0);
8916194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        final CharSequence value = ta.getText(R.styleable.ViewTag_value);
892451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        view.setTag(key, value);
893451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        ta.recycle();
894451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette
8956194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        consumeChildElements(parser);
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8986194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    private void parseInclude(XmlPullParser parser, Context context, View parent,
8996194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            AttributeSet attrs) throws XmlPullParserException, IOException {
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (parent instanceof ViewGroup) {
9036194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            // Apply a theme wrapper, if requested. This is sort of a weird
9046194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            // edge case, since developers think the <include> overwrites
9056194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            // values in the AttributeSet of the included View. So, if the
9066194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            // included View has a theme attribute, we'll need to ignore it.
90733e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
90833e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            final int themeResId = ta.getResourceId(0, 0);
9096194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            final boolean hasThemeOverride = themeResId != 0;
9106194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            if (hasThemeOverride) {
91133e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette                context = new ContextThemeWrapper(context, themeResId);
91233e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            }
91333e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            ta.recycle();
91433e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette
91533e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            // If the layout is pointing to a theme attribute, we have to
91633e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            // massage the value to get a resource identifier out of it.
91733e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0);
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (layout == 0) {
91933e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette                final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
9206194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                if (value == null || value.length() <= 0) {
92133e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette                    throw new InflateException("You must specify a layout in the"
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + " include tag: <include layout=\"@layout/layoutID\" />");
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
92433e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette
9256194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                // Attempt to resolve the "?attr/name" string to an identifier.
92633e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette                layout = context.getResources().getIdentifier(value.substring(1), null, null);
92733e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            }
92833e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette
92933e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            // The layout might be referencing a theme attribute.
93033e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            if (mTempValue == null) {
93133e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette                mTempValue = new TypedValue();
93233e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            }
93333e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            if (layout != 0 && context.getTheme().resolveAttribute(layout, mTempValue, true)) {
93433e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette                layout = mTempValue.resourceId;
93533e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            }
93633e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette
93733e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette            if (layout == 0) {
93833e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette                final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
93933e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette                throw new InflateException("You must specify a valid layout "
94033e3cdab5bb20fc265b75b541fd9e1837269cc50Alan Viverette                        + "reference. The layout ID " + value + " is not valid.");
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
9426194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                final XmlResourceParser childParser = context.getResources().getLayout(layout);
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    while ((type = childParser.next()) != XmlPullParser.START_TAG &&
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            type != XmlPullParser.END_DOCUMENT) {
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Empty.
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (type != XmlPullParser.START_TAG) {
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        throw new InflateException(childParser.getPositionDescription() +
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                ": No start tag found!");
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final String childName = childParser.getName();
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (TAG_MERGE.equals(childName)) {
9606194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                        // The <merge> tag doesn't support android:theme, so
9616194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                        // nothing special to do here.
9626194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                        rInflate(childParser, parent, context, childAttrs, false);
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
9646194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                        final View view = createViewFromTag(parent, childName,
9656194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                                context, childAttrs, hasThemeOverride);
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final ViewGroup group = (ViewGroup) parent;
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
968e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viverette                        final TypedArray a = context.obtainStyledAttributes(
969e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viverette                                attrs, R.styleable.Include);
970e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viverette                        final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
971e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viverette                        final int visibility = a.getInt(R.styleable.Include_visibility, -1);
972e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viverette                        a.recycle();
973e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viverette
97484aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                        // We try to load the layout params set in the <include /> tag.
97584aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                        // If the parent can't generate layout params (ex. missing width
97684aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                        // or height for the framework ViewGroups, though this is not
97784aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                        // necessarily true of all ViewGroups) then we expect it to throw
97884aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                        // a runtime exception.
97984aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                        // We catch this exception and set localParams accordingly: true
98084aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                        // means we successfully loaded layout params from the <include>
98184aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                        // tag, false means we need to rely on the included layout params.
982579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        ViewGroup.LayoutParams params = null;
98384aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                        try {
98484aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                            params = group.generateLayoutParams(attrs);
98584aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                        } catch (RuntimeException e) {
98684aa2fb65ab1ac99d6e59bd9d3398cfabc8cccc1Alan Viverette                            // Ignore, just fail over to child attrs.
987579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        }
988e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viverette                        if (params == null) {
989e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viverette                            params = group.generateLayoutParams(childAttrs);
990e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viverette                        }
991e8489cd5f578d8f60f0f48bf6d40785488f4092cAlan Viverette                        view.setLayoutParams(params);
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Inflate all children.
9946194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette                        rInflateChildren(childParser, view, childAttrs, true);
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (id != View.NO_ID) {
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            view.setId(id);
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        switch (visibility) {
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 0:
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.VISIBLE);
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 1:
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.INVISIBLE);
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 2:
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.GONE);
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        group.addView(view);
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } finally {
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childParser.close();
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new InflateException("<include /> can only be used inside of a ViewGroup");
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10226194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        LayoutInflater.consumeChildElements(parser);
10236194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    }
10246194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette
10256194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    /**
10266194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * <strong>Note:</strong> default visibility so that
10276194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     * LayoutInflater_Delegate can call it.
10286194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette     */
10296194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette    final static void consumeChildElements(XmlPullParser parser)
10306194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette            throws XmlPullParserException, IOException {
10316194d728cf9d43a3a40f8a0e96283d92887c5bcdAlan Viverette        int type;
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currentDepth = parser.getDepth();
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (((type = parser.next()) != XmlPullParser.END_TAG ||
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Empty
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10379c1223a71397b565f38015c07cae57a5015a6500Romain Guy    }
10389c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10399c1223a71397b565f38015c07cae57a5015a6500Romain Guy    private static class BlinkLayout extends FrameLayout {
10409c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private static final int MESSAGE_BLINK = 0x42;
10419c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private static final int BLINK_DELAY = 500;
10429c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10439c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private boolean mBlink;
10449c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private boolean mBlinkState;
10459c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private final Handler mHandler;
10469c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10479c1223a71397b565f38015c07cae57a5015a6500Romain Guy        public BlinkLayout(Context context, AttributeSet attrs) {
10489c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super(context, attrs);
10499c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler = new Handler(new Handler.Callback() {
10509c1223a71397b565f38015c07cae57a5015a6500Romain Guy                @Override
10519c1223a71397b565f38015c07cae57a5015a6500Romain Guy                public boolean handleMessage(Message msg) {
10529c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    if (msg.what == MESSAGE_BLINK) {
10539c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        if (mBlink) {
10549c1223a71397b565f38015c07cae57a5015a6500Romain Guy                            mBlinkState = !mBlinkState;
10559c1223a71397b565f38015c07cae57a5015a6500Romain Guy                            makeBlink();
10569c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        }
10579c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        invalidate();
10589c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        return true;
10599c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    }
10609c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    return false;
10619c1223a71397b565f38015c07cae57a5015a6500Romain Guy                }
10629c1223a71397b565f38015c07cae57a5015a6500Romain Guy            });
10639c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
10649c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10659c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private void makeBlink() {
10669c1223a71397b565f38015c07cae57a5015a6500Romain Guy            Message message = mHandler.obtainMessage(MESSAGE_BLINK);
10679c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler.sendMessageDelayed(message, BLINK_DELAY);
10689c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
10699c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10709c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
10719c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void onAttachedToWindow() {
10729c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super.onAttachedToWindow();
10739c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10749c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlink = true;
10759c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlinkState = true;
10769c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10779c1223a71397b565f38015c07cae57a5015a6500Romain Guy            makeBlink();
10789c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
10799c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10809c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
10819c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void onDetachedFromWindow() {
10829c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super.onDetachedFromWindow();
10839c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10849c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlink = false;
10859c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlinkState = true;
10869c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10879c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler.removeMessages(MESSAGE_BLINK);
10889c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
10899c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10909c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
10919c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void dispatchDraw(Canvas canvas) {
10929c1223a71397b565f38015c07cae57a5015a6500Romain Guy            if (mBlinkState) {
10939c1223a71397b565f38015c07cae57a5015a6500Romain Guy                super.dispatchDraw(canvas);
10949c1223a71397b565f38015c07cae57a5015a6500Romain Guy            }
10959c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
10969c1223a71397b565f38015c07cae57a5015a6500Romain Guy    }
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1098