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
199c1223a71397b565f38015c07cae57a5015a6500Romain Guyimport android.graphics.Canvas;
209c1223a71397b565f38015c07cae57a5015a6500Romain Guyimport android.os.Handler;
219c1223a71397b565f38015c07cae57a5015a6500Romain Guyimport android.os.Message;
2209f7b93a184d12e5ed584206d903982b3e0915e5Romain Guyimport android.os.Trace;
239c1223a71397b565f38015c07cae57a5015a6500Romain Guyimport android.widget.FrameLayout;
240810b63739c9981f993063749f804b54faed0ba5Alan Viverette
253030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport org.xmlpull.v1.XmlPullParser;
263030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport org.xmlpull.v1.XmlPullParserException;
273030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
290810b63739c9981f993063749f804b54faed0ba5Alan Viveretteimport android.content.res.Resources;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.XmlResourceParser;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
330810b63739c9981f993063749f804b54faed0ba5Alan Viveretteimport android.util.Log;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Xml;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Constructor;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
4193dc642eaf48e3db58c4929df26283fbc5fd663fScott Main * Instantiates a layout XML file into its corresponding {@link android.view.View}
4293dc642eaf48e3db58c4929df26283fbc5fd663fScott Main * objects. It is never used directly. Instead, use
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.app.Activity#getLayoutInflater()} or
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Context#getSystemService} to retrieve a standard LayoutInflater instance
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that is already hooked up to the current context and correctly configured
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for the device you are running on.  For example:
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
49bd6fda11d287ba8ac749e06053dc9488653d1471Christian Mehlmauer *      (Context.LAYOUT_INFLATER_SERVICE);</pre>
50579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke *
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To create a new LayoutInflater with an additional {@link Factory} for your
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * own views, you can use {@link #cloneInContext} to clone an existing
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ViewFactory, and then call {@link #setFactory} on it to include your
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Factory.
56579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke *
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For performance reasons, view inflation relies heavily on pre-processing of
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * XML files that is done at build time. Therefore, it is not currently possible
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it only works with an XmlPullParser returned from a compiled resource
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (R.<em>something</em> file.)
63579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke *
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see Context#getSystemService
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class LayoutInflater {
670810b63739c9981f993063749f804b54faed0ba5Alan Viverette    private static final String TAG = LayoutInflater.class.getSimpleName();
680810b63739c9981f993063749f804b54faed0ba5Alan Viverette    private static final boolean DEBUG = false;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This field should be made private, so it is hidden from the SDK.
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected final Context mContext;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these are optional, set by the caller
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mFactorySet;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Factory mFactory;
79625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    private Factory2 mFactory2;
80420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    private Factory2 mPrivateFactory;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Filter mFilter;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
837f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    final Object[] mConstructorArgs = new Object[2];
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
857f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    static final Class<?>[] mConstructorSignature = new Class[] {
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Context.class, AttributeSet.class};
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
883030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne    private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
893030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            new HashMap<String, Constructor<? extends View>>();
90579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String, Boolean> mFilterMap;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_MERGE = "merge";
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_INCLUDE = "include";
959c1223a71397b565f38015c07cae57a5015a6500Romain Guy    private static final String TAG_1995 = "blink";
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_REQUEST_FOCUS = "requestFocus";
97451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    private static final String TAG_TAG = "tag";
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
99ef259e4484deb69ada76970e26f2b2542b1fe4c1Alan Viverette    private static final int[] ATTRS_THEME = new int[] {
100ef259e4484deb69ada76970e26f2b2542b1fe4c1Alan Viverette            com.android.internal.R.attr.theme };
10124927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to be inflated.
105579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Filter {
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Hook to allow clients of the LayoutInflater to restrict the set of Views
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * that are allowed to be inflated.
111579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param clazz The class object for the View that is about to be inflated
113579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return True if this class is allowed to be inflated, or false otherwise
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
116e6ac8b9aade9443ab8456c8f7a47cdfba3b70266Gilles Debunne        @SuppressWarnings("unchecked")
117e6ac8b9aade9443ab8456c8f7a47cdfba3b70266Gilles Debunne        boolean onLoadClass(Class clazz);
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
119579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Factory {
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Hook you can supply that is called when inflating from a LayoutInflater.
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * You can use this to customize the tag names available in your XML
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * layout files.
125579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note that it is good practice to prefix these custom names with your
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * package (i.e., com.coolcompany.apps) to avoid conflicts with system
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * names.
130579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param name Tag name to be inflated.
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param context The context the view is being created in.
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param attrs Inflation attributes as specified in XML file.
134579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return View Newly created view. Return null for the default
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *         behavior.
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View onCreateView(String name, Context context, AttributeSet attrs);
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
141625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public interface Factory2 extends Factory {
142625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        /**
143625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * Version of {@link #onCreateView(String, Context, AttributeSet)}
144625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * that also supplies the parent that the view created view will be
145625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * placed in.
146625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *
147625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param parent The parent that the created view will be placed
148625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * in; <em>note that this may be null</em>.
149625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param name Tag name to be inflated.
150625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param context The context the view is being created in.
151625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param attrs Inflation attributes as specified in XML file.
152625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *
153625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @return View Newly created view. Return null for the default
154625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *         behavior.
155625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         */
156625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        public View onCreateView(View parent, String name, Context context, AttributeSet attrs);
157625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
158625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
159625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    private static class FactoryMerger implements Factory2 {
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final Factory mF1, mF2;
161625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        private final Factory2 mF12, mF22;
162579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
163625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mF1 = f1;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mF2 = f2;
166625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mF12 = f12;
167625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mF22 = f22;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
169579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View onCreateView(String name, Context context, AttributeSet attrs) {
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View v = mF1.onCreateView(name, context, attrs);
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (v != null) return v;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mF2.onCreateView(name, context, attrs);
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
175625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
176625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
177625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            View v = mF12 != null ? mF12.onCreateView(parent, name, context, attrs)
178625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                    : mF1.onCreateView(name, context, attrs);
179625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            if (v != null) return v;
180625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            return mF22 != null ? mF22.onCreateView(parent, name, context, attrs)
181625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                    : mF2.onCreateView(name, context, attrs);
182625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
184579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new LayoutInflater instance associated with a particular Context.
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Applications will almost always want to use
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link Context#getSystemService Context.getSystemService()} to retrieve
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
190579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context The Context in which this LayoutInflater will create its
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Views; most importantly, this supplies the theme from which the default
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * values for their attributes are retrieved.
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected LayoutInflater(Context context) {
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new LayoutInflater instance that is a copy of an existing
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater, optionally with its Context changed.  For use in
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementing {@link #cloneInContext}.
203579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param original The original LayoutInflater to copy.
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param newContext The new Context to use.
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected LayoutInflater(LayoutInflater original, Context newContext) {
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = newContext;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFactory = original.mFactory;
210625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        mFactory2 = original.mFactory2;
211420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn        mPrivateFactory = original.mPrivateFactory;
2120c7bb33e03392416fc98c27738d1bcca386a6b2fDan Sandler        setFilter(original.mFilter);
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
214579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Obtains the LayoutInflater from the given context.
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static LayoutInflater from(Context context) {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LayoutInflater LayoutInflater =
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LayoutInflater == null) {
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new AssertionError("LayoutInflater not found.");
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return LayoutInflater;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a copy of the existing LayoutInflater object, with the copy
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pointing to a different Context than the original.  This is used by
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ContextThemeWrapper} to create a new LayoutInflater to go along
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with the new Context theme.
232579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param newContext The new Context to associate with the new LayoutInflater.
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * May be the same as the original Context if desired.
235579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a brand spanking new LayoutInflater object associated with
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the given Context.
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract LayoutInflater cloneInContext(Context newContext);
240579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the context we are running in, for access to resources, class
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * loader, etc.
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Context getContext() {
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContext;
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
250625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Return the current {@link Factory} (or null). This is called on each element
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * name. If the factory returns a View, add that to the hierarchy. If it
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returns null, proceed to call onCreateView(name).
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final Factory getFactory() {
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFactory;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
259625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Return the current {@link Factory2}.  Returns null if no factory is set
260625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * or the set factory does not implement the {@link Factory2} interface.
261625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * This is called on each element
262625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * name. If the factory returns a View, add that to the hierarchy. If it
263625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * returns null, proceed to call onCreateView(name).
264625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
265625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public final Factory2 getFactory2() {
266625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        return mFactory2;
267625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
268625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
269625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Attach a custom Factory interface for creating views while using
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this LayoutInflater.  This must not be null, and can only be set once;
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after setting, you can not change the factory.  This is
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called on each element name as the xml is parsed. If the factory returns
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a View, that is added to the hierarchy. If it returns null, the next
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * factory default {@link #onCreateView} method is called.
276579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If you have an existing
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater and want to add your own factory to it, use
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #cloneInContext} to clone the existing instance and then you
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can use this function (once) on the returned new instance.  This will
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * merge your own factory with whatever factory the original instance is
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * using.
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFactory(Factory factory) {
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFactorySet) {
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (factory == null) {
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new NullPointerException("Given factory can not be null");
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFactorySet = true;
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFactory == null) {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFactory = factory;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
295625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mFactory = new FactoryMerger(factory, null, mFactory, mFactory2);
296625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
297625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
298625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
299625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
300625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Like {@link #setFactory}, but allows you to set a {@link Factory2}
301625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * interface.
302625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
303625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public void setFactory2(Factory2 factory) {
304625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (mFactorySet) {
305625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
306625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
307625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (factory == null) {
308625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throw new NullPointerException("Given factory can not be null");
309625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
310625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        mFactorySet = true;
311625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (mFactory == null) {
312625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mFactory = mFactory2 = factory;
313625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        } else {
314371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell            mFactory = mFactory2 = new FactoryMerger(factory, factory, mFactory, mFactory2);
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
319420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn     * @hide for use by framework
320420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn     */
321420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    public void setPrivateFactory(Factory2 factory) {
322371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell        if (mPrivateFactory == null) {
323371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell            mPrivateFactory = factory;
324371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell        } else {
325371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell            mPrivateFactory = new FactoryMerger(factory, factory, mPrivateFactory, mPrivateFactory);
326371a809179c843d7ae661a10bc9b4b8cfcaff566Adam Powell        }
327420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    }
328420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn
329420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    /**
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The {@link Filter} currently used by this LayoutInflater to restrict the set of Views
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that are allowed to be inflated.
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Filter getFilter() {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFilter;
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
336579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * throw an {@link InflateException}. This filter will replace any previous filter set on this
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater.
342579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param filter The Filter which restricts the set of Views that are allowed to be inflated.
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        This filter will replace any previous filter set on this LayoutInflater.
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFilter(Filter filter) {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilter = filter;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (filter != null) {
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFilterMap = new HashMap<String, Boolean>();
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml resource. Throws
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
356579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resource ID for an XML layout resource to load (e.g.,
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <code>R.layout.main_page</code>)
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy.
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied,
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         this is the root View; otherwise it is the root of the inflated
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         XML file.
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(int resource, ViewGroup root) {
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return inflate(resource, root, root != null);
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml node. Throws
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error. *
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * reasons, view inflation relies heavily on pre-processing of XML files
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that is done at build time. Therefore, it is not currently possible to
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
376579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parser XML dom node containing the description of the view
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy.
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy.
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied,
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         this is the root View; otherwise it is the root of the inflated
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         XML file.
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(XmlPullParser parser, ViewGroup root) {
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return inflate(parser, root, root != null);
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml resource. Throws
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
391579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resource ID for an XML layout resource to load (e.g.,
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <code>R.layout.main_page</code>)
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy (if
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <em>attachToRoot</em> is true), or else simply an object that
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        provides a set of LayoutParams values for root of the returned
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy (if <em>attachToRoot</em> is false.)
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attachToRoot Whether the inflated hierarchy should be attached to
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        the root parameter? If false, root is only used to create the
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        correct subclass of LayoutParams for the root view in the XML.
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied and
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         attachToRoot is true, this is root; otherwise it is the root of
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the inflated XML file.
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
4060810b63739c9981f993063749f804b54faed0ba5Alan Viverette        final Resources res = getContext().getResources();
4070810b63739c9981f993063749f804b54faed0ba5Alan Viverette        if (DEBUG) {
4080810b63739c9981f993063749f804b54faed0ba5Alan Viverette            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
4090810b63739c9981f993063749f804b54faed0ba5Alan Viverette                    + Integer.toHexString(resource) + ")");
4100810b63739c9981f993063749f804b54faed0ba5Alan Viverette        }
4110810b63739c9981f993063749f804b54faed0ba5Alan Viverette
4120810b63739c9981f993063749f804b54faed0ba5Alan Viverette        final XmlResourceParser parser = res.getLayout(resource);
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return inflate(parser, root, attachToRoot);
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            parser.close();
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified XML node. Throws
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * reasons, view inflation relies heavily on pre-processing of XML files
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that is done at build time. Therefore, it is not currently possible to
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
428579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parser XML dom node containing the description of the view
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy.
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy (if
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <em>attachToRoot</em> is true), or else simply an object that
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        provides a set of LayoutParams values for root of the returned
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy (if <em>attachToRoot</em> is false.)
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attachToRoot Whether the inflated hierarchy should be attached to
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        the root parameter? If false, root is only used to create the
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        correct subclass of LayoutParams for the root view in the XML.
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied and
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         attachToRoot is true, this is root; otherwise it is the root of
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the inflated XML file.
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mConstructorArgs) {
44409f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");
44509f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final AttributeSet attrs = Xml.asAttributeSet(parser);
4479dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn            Context lastContext = (Context)mConstructorArgs[0];
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstructorArgs[0] = mContext;
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View result = root;
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Look for the root node.
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int type;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while ((type = parser.next()) != XmlPullParser.START_TAG &&
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        type != XmlPullParser.END_DOCUMENT) {
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Empty
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type != XmlPullParser.START_TAG) {
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException(parser.getPositionDescription()
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + ": No start tag found!");
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final String name = parser.getName();
465579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) {
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("**************************");
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("Creating root view: "
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + name);
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("**************************");
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (TAG_MERGE.equals(name)) {
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root == null || !attachToRoot) {
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        throw new InflateException("<merge /> can be used only with a valid "
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                + "ViewGroup root and attachToRoot=true");
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
47924927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                    rInflate(parser, root, attrs, false, false);
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Temp is the root view that was found in the xml
48224927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                    final View temp = createViewFromTag(root, name, attrs, false);
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ViewGroup.LayoutParams params = null;
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root != null) {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (DEBUG) {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.out.println("Creating params from root: " +
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    root);
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Create layout params that match root, if supplied
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        params = root.generateLayoutParams(attrs);
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!attachToRoot) {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // Set the layout params for temp if we are not
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // attaching. (If we are, we use addView, below)
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            temp.setLayoutParams(params);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (DEBUG) {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        System.out.println("-----> start inflating children");
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Inflate all children under temp
50424927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                    rInflate(parser, temp, attrs, true, true);
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (DEBUG) {
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        System.out.println("-----> done inflating children");
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We are supposed to attach all the views we found (int temp)
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to root. Do that now.
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root != null && attachToRoot) {
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        root.addView(temp, params);
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Decide whether to return the root that was passed in or the
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // top view found in xml.
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root == null || !attachToRoot) {
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        result = temp;
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (XmlPullParserException e) {
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InflateException ex = new InflateException(e.getMessage());
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ex.initCause(e);
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw ex;
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InflateException ex = new InflateException(
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        parser.getPositionDescription()
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": " + e.getMessage());
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ex.initCause(e);
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw ex;
5329dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn            } finally {
5339dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                // Don't retain static reference on context.
5349dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                mConstructorArgs[0] = lastContext;
5359dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                mConstructorArgs[1] = null;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
53809f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
53909f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return result;
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Low-level function for instantiating a view by name. This attempts to
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instantiate a view class of the given <var>name</var> found in this
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater's ClassLoader.
548579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * There are two things that can happen in an error case: either the
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * exception describing the error will be thrown, or a null will be
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned. You must deal with both possibilities -- the former will happen
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the first time createView() is called for a class of a particular name,
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the latter every time there-after for that class name.
555579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param name The full name of the class to be instantiated.
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attrs The XML attributes supplied for this instance.
558579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
5593030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne     * @return View The newly instantiated view, or null.
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final View createView(String name, String prefix, AttributeSet attrs)
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ClassNotFoundException, InflateException {
5633030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        Constructor<? extends View> constructor = sConstructorMap.get(name);
5643030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        Class<? extends View> clazz = null;
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
56709f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy            Trace.traceBegin(Trace.TRACE_TAG_VIEW, name);
56809f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (constructor == null) {
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Class not found in the cache, see if it's real, and try to add it
571d03b880836bcc4fae83a95458e0709cd45aa6313Romain Guy                clazz = mContext.getClassLoader().loadClass(
5723030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                        prefix != null ? (prefix + name) : name).asSubclass(View.class);
573579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFilter != null && clazz != null) {
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean allowed = mFilter.onLoadClass(clazz);
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!allowed) {
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        failNotAllowed(name, prefix, attrs);
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                constructor = clazz.getConstructor(mConstructorSignature);
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sConstructorMap.put(name, constructor);
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If we have a filter, apply it to cached constructor
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFilter != null) {
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Have we seen this name before?
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Boolean allowedState = mFilterMap.get(name);
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (allowedState == null) {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // New class -- remember whether it is allowed
589d03b880836bcc4fae83a95458e0709cd45aa6313Romain Guy                        clazz = mContext.getClassLoader().loadClass(
5903030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                                prefix != null ? (prefix + name) : name).asSubclass(View.class);
591579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mFilterMap.put(name, allowed);
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!allowed) {
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            failNotAllowed(name, prefix, attrs);
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (allowedState.equals(Boolean.FALSE)) {
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        failNotAllowed(name, prefix, attrs);
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Object[] args = mConstructorArgs;
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            args[1] = attrs;
605b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey
606e3abd2ccbef4c50b48df3605c65d732fa49a980bJeff Hao            constructor.setAccessible(true);
607b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            final View view = constructor.newInstance(args);
608b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            if (view instanceof ViewStub) {
609a9ddb8dc23b253c53f24ceb81e9d596c072d834eAlan Viverette                // Use the same context when inflating ViewStub later.
610b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey                final ViewStub viewStub = (ViewStub) view;
611a9ddb8dc23b253c53f24ceb81e9d596c072d834eAlan Viverette                viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
612b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            }
613b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            return view;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (NoSuchMethodException e) {
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class "
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + (prefix != null ? (prefix + name) : name));
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6223030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        } catch (ClassCastException e) {
6233030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            // If loaded class is not a View subclass
6243030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            InflateException ie = new InflateException(attrs.getPositionDescription()
6253030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                    + ": Class is not a View "
6263030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                    + (prefix != null ? (prefix + name) : name));
6273030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            ie.initCause(e);
6283030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            throw ie;
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (ClassNotFoundException e) {
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If loadClass fails, we should propagate the exception.
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class "
635d03b880836bcc4fae83a95458e0709cd45aa6313Romain Guy                    + (clazz == null ? "<unknown>" : clazz.getName()));
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
63809f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy        } finally {
63909f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6443030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne     * Throw an exception because the specified class is not allowed to be inflated.
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
6479c1223a71397b565f38015c07cae57a5015a6500Romain Guy        throw new InflateException(attrs.getPositionDescription()
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + ": Class not allowed to be inflated "
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + (prefix != null ? (prefix + name) : name));
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This routine is responsible for creating the correct subclass of View
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * given the xml element name. Override it to handle custom view objects. If
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * you override this in your subclass be sure to call through to
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * super.onCreateView(name) for names you do not recognize.
657579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param name The fully qualified class name of the View to be create.
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attrs An AttributeSet of attributes to apply to the View.
660579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return View The View created.
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected View onCreateView(String name, AttributeSet attrs)
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ClassNotFoundException {
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return createView(name, "android.view.", attrs);
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
668625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
669625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Version of {@link #onCreateView(String, AttributeSet)} that also
670430742f09063574271e6c4091de13b9b9e762514Chet Haase     * takes the future parent of the view being constructed.  The default
671625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * implementation simply calls {@link #onCreateView(String, AttributeSet)}.
672625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     *
673625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param parent The future parent of the returned view.  <em>Note that
674625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * this may be null.</em>
675625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param name The fully qualified class name of the View to be create.
676625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param attrs An AttributeSet of attributes to apply to the View.
677625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     *
678625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @return View The View created.
679625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
680625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    protected View onCreateView(View parent, String name, AttributeSet attrs)
681625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throws ClassNotFoundException {
682625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        return onCreateView(name, attrs);
683625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
684625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
68524927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette    /**
68624927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     * Creates a view from a tag name using the supplied attribute set.
68724927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     * <p>
68824927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     * If {@code inheritContext} is true and the parent is non-null, the view
68924927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     * will be inflated in parent view's context. If the view specifies a
69024927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     * &lt;theme&gt; attribute, the inflation context will be wrapped with the
69124927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     * specified theme.
69224927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     * <p>
69324927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     * Note: Default visibility so the BridgeInflater can override it.
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
69524927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette    View createViewFromTag(View parent, String name, AttributeSet attrs, boolean inheritContext) {
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (name.equals("view")) {
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            name = attrs.getAttributeValue(null, "class");
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
70024927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        Context viewContext;
70124927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        if (parent != null && inheritContext) {
70224927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            viewContext = parent.getContext();
70324927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        } else {
70424927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            viewContext = mContext;
70524927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        }
70624927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette
70724927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        // Apply a theme wrapper, if requested.
708ef259e4484deb69ada76970e26f2b2542b1fe4c1Alan Viverette        final TypedArray ta = viewContext.obtainStyledAttributes(attrs, ATTRS_THEME);
709ef259e4484deb69ada76970e26f2b2542b1fe4c1Alan Viverette        final int themeResId = ta.getResourceId(0, 0);
71024927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        if (themeResId != 0) {
71124927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            viewContext = new ContextThemeWrapper(viewContext, themeResId);
71224927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        }
713ef259e4484deb69ada76970e26f2b2542b1fe4c1Alan Viverette        ta.recycle();
71424927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette
71524927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        if (name.equals(TAG_1995)) {
71624927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            // Let's party like it's 1995!
71724927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            return new BlinkLayout(viewContext, attrs);
71824927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette        }
71924927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG) System.out.println("******** Creating view: " + name);
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
723625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            View view;
72424927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            if (mFactory2 != null) {
72524927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                view = mFactory2.onCreateView(parent, name, viewContext, attrs);
72624927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            } else if (mFactory != null) {
72724927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                view = mFactory.onCreateView(name, viewContext, attrs);
72824927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            } else {
72924927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                view = null;
73024927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            }
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
732420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn            if (view == null && mPrivateFactory != null) {
73324927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                view = mPrivateFactory.onCreateView(parent, name, viewContext, attrs);
734420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn            }
73524927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (view == null) {
73724927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                final Object lastContext = mConstructorArgs[0];
73824927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                mConstructorArgs[0] = viewContext;
73924927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                try {
74024927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                    if (-1 == name.indexOf('.')) {
74124927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                        view = onCreateView(parent, name, attrs);
74224927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                    } else {
74324927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                        view = createView(name, null, attrs);
74424927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                    }
74524927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                } finally {
74624927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                    mConstructorArgs[0] = lastContext;
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) System.out.println("Created view is: " + view);
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return view;
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (InflateException e) {
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (ClassNotFoundException e) {
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class " + name);
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class " + name);
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Recursive method used to descend down the xml hierarchy and instantiate
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * views, instantiate their children, and then call onFinishInflate().
77324927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     *
77424927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     * @param inheritContext Whether the root view should be inflated in its
77524927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     *            parent's context. This should be true when called inflating
77624927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette     *            child views recursively, or false otherwise.
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7787f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs,
77924927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            boolean finishInflate, boolean inheritContext) throws XmlPullParserException,
78024927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            IOException {
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int depth = parser.getDepth();
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (((type = parser.next()) != XmlPullParser.END_TAG ||
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type != XmlPullParser.START_TAG) {
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String name = parser.getName();
793579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (TAG_REQUEST_FOCUS.equals(name)) {
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parseRequestFocus(parser, parent);
796451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette            } else if (TAG_TAG.equals(name)) {
797451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette                parseViewTag(parser, parent, attrs);
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (TAG_INCLUDE.equals(name)) {
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (parser.getDepth() == 0) {
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException("<include /> cannot be the root element");
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
80224927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                parseInclude(parser, parent, attrs, inheritContext);
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (TAG_MERGE.equals(name)) {
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new InflateException("<merge /> must be the root element");
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
80624927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                final View view = createViewFromTag(parent, name, attrs, inheritContext);
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ViewGroup viewGroup = (ViewGroup) parent;
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
80924927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                rInflate(parser, view, attrs, true, true);
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                viewGroup.addView(view, params);
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8149295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy        if (finishInflate) parent.onFinishInflate();
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
817451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    /**
818451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     * Parses a <code>&lt;request-focus&gt;</code> element and requests focus on
819451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     * the containing View.
820451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     */
821451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    private void parseRequestFocus(XmlPullParser parser, View view)
822451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette            throws XmlPullParserException, IOException {
823451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        int type;
824451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        view.requestFocus();
825451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        final int currentDepth = parser.getDepth();
826451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        while (((type = parser.next()) != XmlPullParser.END_TAG ||
827451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette                parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
828451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette            // Empty
829451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        }
830451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    }
831451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette
832451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    /**
833451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     * Parses a <code>&lt;tag&gt;</code> element and sets a keyed tag on the
834451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     * containing View.
835451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette     */
836451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette    private void parseViewTag(XmlPullParser parser, View view, AttributeSet attrs)
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
839451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette
840451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        final TypedArray ta = mContext.obtainStyledAttributes(
841451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette                attrs, com.android.internal.R.styleable.ViewTag);
842451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        final int key = ta.getResourceId(com.android.internal.R.styleable.ViewTag_id, 0);
843451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        final CharSequence value = ta.getText(com.android.internal.R.styleable.ViewTag_value);
844451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        view.setTag(key, value);
845451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette        ta.recycle();
846451a3417e97d9d3bb835290a65f9af30b112c789Alan Viverette
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currentDepth = parser.getDepth();
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (((type = parser.next()) != XmlPullParser.END_TAG ||
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Empty
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
85424927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette    private void parseInclude(XmlPullParser parser, View parent, AttributeSet attrs,
85524927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette            boolean inheritContext) throws XmlPullParserException, IOException {
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (parent instanceof ViewGroup) {
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int layout = attrs.getAttributeResourceValue(null, "layout", 0);
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (layout == 0) {
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final String value = attrs.getAttributeValue(null, "layout");
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value == null) {
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException("You must specifiy a layout in the"
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + " include tag: <include layout=\"@layout/layoutID\" />");
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException("You must specifiy a valid layout "
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + "reference. The layout ID " + value + " is not valid.");
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final XmlResourceParser childParser =
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        getContext().getResources().getLayout(layout);
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    while ((type = childParser.next()) != XmlPullParser.START_TAG &&
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            type != XmlPullParser.END_DOCUMENT) {
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Empty.
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (type != XmlPullParser.START_TAG) {
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        throw new InflateException(childParser.getPositionDescription() +
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                ": No start tag found!");
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final String childName = childParser.getName();
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (TAG_MERGE.equals(childName)) {
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Inflate all children.
89024927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                        rInflate(childParser, parent, childAttrs, false, inheritContext);
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
89224927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                        final View view = createViewFromTag(parent, childName, childAttrs,
89324927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                                inheritContext);
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final ViewGroup group = (ViewGroup) parent;
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We try to load the layout params set in the <include /> tag. If
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // they don't exist, we will rely on the layout params set in the
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // included XML file.
899579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        // During a layoutparams generation, a runtime exception is thrown
900579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        // if either layout_width or layout_height is missing. We catch
901579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        // this exception and set localParams accordingly: true means we
902579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        // successfully loaded layout params from the <include /> tag,
903579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        // false means we need to rely on the included layout params.
904579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        ViewGroup.LayoutParams params = null;
905579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        try {
906579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                            params = group.generateLayoutParams(attrs);
907579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        } catch (RuntimeException e) {
908579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                            params = group.generateLayoutParams(childAttrs);
909579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        } finally {
910579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                            if (params != null) {
911579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                                view.setLayoutParams(params);
912579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                            }
913579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        }
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Inflate all children.
91624927f2798fdeee3aa4fa13dee5acfa218e993e3Alan Viverette                        rInflate(childParser, view, childAttrs, true, true);
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Attempt to override the included layout's android:id with the
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // one set on the <include /> tag itself.
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        TypedArray a = mContext.obtainStyledAttributes(attrs,
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            com.android.internal.R.styleable.View, 0, 0);
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int id = a.getResourceId(com.android.internal.R.styleable.View_id, View.NO_ID);
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // While we're at it, let's try to override android:visibility.
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int visibility = a.getInt(com.android.internal.R.styleable.View_visibility, -1);
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        a.recycle();
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (id != View.NO_ID) {
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            view.setId(id);
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        switch (visibility) {
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 0:
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.VISIBLE);
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 1:
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.INVISIBLE);
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 2:
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.GONE);
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        group.addView(view);
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } finally {
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childParser.close();
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new InflateException("<include /> can only be used inside of a ViewGroup");
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currentDepth = parser.getDepth();
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (((type = parser.next()) != XmlPullParser.END_TAG ||
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Empty
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9589c1223a71397b565f38015c07cae57a5015a6500Romain Guy    }
9599c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9609c1223a71397b565f38015c07cae57a5015a6500Romain Guy    private static class BlinkLayout extends FrameLayout {
9619c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private static final int MESSAGE_BLINK = 0x42;
9629c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private static final int BLINK_DELAY = 500;
9639c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9649c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private boolean mBlink;
9659c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private boolean mBlinkState;
9669c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private final Handler mHandler;
9679c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9689c1223a71397b565f38015c07cae57a5015a6500Romain Guy        public BlinkLayout(Context context, AttributeSet attrs) {
9699c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super(context, attrs);
9709c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler = new Handler(new Handler.Callback() {
9719c1223a71397b565f38015c07cae57a5015a6500Romain Guy                @Override
9729c1223a71397b565f38015c07cae57a5015a6500Romain Guy                public boolean handleMessage(Message msg) {
9739c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    if (msg.what == MESSAGE_BLINK) {
9749c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        if (mBlink) {
9759c1223a71397b565f38015c07cae57a5015a6500Romain Guy                            mBlinkState = !mBlinkState;
9769c1223a71397b565f38015c07cae57a5015a6500Romain Guy                            makeBlink();
9779c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        }
9789c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        invalidate();
9799c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        return true;
9809c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    }
9819c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    return false;
9829c1223a71397b565f38015c07cae57a5015a6500Romain Guy                }
9839c1223a71397b565f38015c07cae57a5015a6500Romain Guy            });
9849c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
9859c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9869c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private void makeBlink() {
9879c1223a71397b565f38015c07cae57a5015a6500Romain Guy            Message message = mHandler.obtainMessage(MESSAGE_BLINK);
9889c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler.sendMessageDelayed(message, BLINK_DELAY);
9899c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
9909c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9919c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
9929c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void onAttachedToWindow() {
9939c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super.onAttachedToWindow();
9949c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9959c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlink = true;
9969c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlinkState = true;
9979c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9989c1223a71397b565f38015c07cae57a5015a6500Romain Guy            makeBlink();
9999c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
10009c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10019c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
10029c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void onDetachedFromWindow() {
10039c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super.onDetachedFromWindow();
10049c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10059c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlink = false;
10069c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlinkState = true;
10079c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10089c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler.removeMessages(MESSAGE_BLINK);
10099c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
10109c1223a71397b565f38015c07cae57a5015a6500Romain Guy
10119c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
10129c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void dispatchDraw(Canvas canvas) {
10139c1223a71397b565f38015c07cae57a5015a6500Romain Guy            if (mBlinkState) {
10149c1223a71397b565f38015c07cae57a5015a6500Romain Guy                super.dispatchDraw(canvas);
10159c1223a71397b565f38015c07cae57a5015a6500Romain Guy            }
10169c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
10179c1223a71397b565f38015c07cae57a5015a6500Romain Guy    }
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1019