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;
243030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport org.xmlpull.v1.XmlPullParser;
253030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport org.xmlpull.v1.XmlPullParserException;
263030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.XmlResourceParser;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Xml;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Constructor;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3893dc642eaf48e3db58c4929df26283fbc5fd663fScott Main * Instantiates a layout XML file into its corresponding {@link android.view.View}
3993dc642eaf48e3db58c4929df26283fbc5fd663fScott Main * objects. It is never used directly. Instead, use
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.app.Activity#getLayoutInflater()} or
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Context#getSystemService} to retrieve a standard LayoutInflater instance
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that is already hooked up to the current context and correctly configured
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for the device you are running on.  For example:
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
46bd6fda11d287ba8ac749e06053dc9488653d1471Christian Mehlmauer *      (Context.LAYOUT_INFLATER_SERVICE);</pre>
47579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke *
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To create a new LayoutInflater with an additional {@link Factory} for your
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * own views, you can use {@link #cloneInContext} to clone an existing
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ViewFactory, and then call {@link #setFactory} on it to include your
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Factory.
53579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke *
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For performance reasons, view inflation relies heavily on pre-processing of
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * XML files that is done at build time. Therefore, it is not currently possible
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it only works with an XmlPullParser returned from a compiled resource
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (R.<em>something</em> file.)
60579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke *
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see Context#getSystemService
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class LayoutInflater {
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final boolean DEBUG = false;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This field should be made private, so it is hidden from the SDK.
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected final Context mContext;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these are optional, set by the caller
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mFactorySet;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Factory mFactory;
75625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    private Factory2 mFactory2;
76420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    private Factory2 mPrivateFactory;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Filter mFilter;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
797f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    final Object[] mConstructorArgs = new Object[2];
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
817f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    static final Class<?>[] mConstructorSignature = new Class[] {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Context.class, AttributeSet.class};
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
843030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne    private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
853030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            new HashMap<String, Constructor<? extends View>>();
86579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String, Boolean> mFilterMap;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_MERGE = "merge";
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_INCLUDE = "include";
919c1223a71397b565f38015c07cae57a5015a6500Romain Guy    private static final String TAG_1995 = "blink";
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_REQUEST_FOCUS = "requestFocus";
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to be inflated.
97579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Filter {
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Hook to allow clients of the LayoutInflater to restrict the set of Views
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * that are allowed to be inflated.
103579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param clazz The class object for the View that is about to be inflated
105579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return True if this class is allowed to be inflated, or false otherwise
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
108e6ac8b9aade9443ab8456c8f7a47cdfba3b70266Gilles Debunne        @SuppressWarnings("unchecked")
109e6ac8b9aade9443ab8456c8f7a47cdfba3b70266Gilles Debunne        boolean onLoadClass(Class clazz);
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
111579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Factory {
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Hook you can supply that is called when inflating from a LayoutInflater.
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * You can use this to customize the tag names available in your XML
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * layout files.
117579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note that it is good practice to prefix these custom names with your
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * package (i.e., com.coolcompany.apps) to avoid conflicts with system
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * names.
122579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param name Tag name to be inflated.
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param context The context the view is being created in.
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param attrs Inflation attributes as specified in XML file.
126579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke         *
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return View Newly created view. Return null for the default
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *         behavior.
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View onCreateView(String name, Context context, AttributeSet attrs);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
133625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public interface Factory2 extends Factory {
134625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        /**
135625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * Version of {@link #onCreateView(String, Context, AttributeSet)}
136625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * that also supplies the parent that the view created view will be
137625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * placed in.
138625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *
139625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param parent The parent that the created view will be placed
140625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * in; <em>note that this may be null</em>.
141625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param name Tag name to be inflated.
142625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param context The context the view is being created in.
143625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param attrs Inflation attributes as specified in XML file.
144625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *
145625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @return View Newly created view. Return null for the default
146625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *         behavior.
147625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         */
148625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        public View onCreateView(View parent, String name, Context context, AttributeSet attrs);
149625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
150625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
151625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    private static class FactoryMerger implements Factory2 {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final Factory mF1, mF2;
153625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        private final Factory2 mF12, mF22;
154579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
155625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mF1 = f1;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mF2 = f2;
158625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mF12 = f12;
159625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mF22 = f22;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
161579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View onCreateView(String name, Context context, AttributeSet attrs) {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View v = mF1.onCreateView(name, context, attrs);
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (v != null) return v;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mF2.onCreateView(name, context, attrs);
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
167625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
168625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
169625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            View v = mF12 != null ? mF12.onCreateView(parent, name, context, attrs)
170625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                    : mF1.onCreateView(name, context, attrs);
171625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            if (v != null) return v;
172625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            return mF22 != null ? mF22.onCreateView(parent, name, context, attrs)
173625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                    : mF2.onCreateView(name, context, attrs);
174625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
176579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new LayoutInflater instance associated with a particular Context.
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Applications will almost always want to use
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link Context#getSystemService Context.getSystemService()} to retrieve
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
182579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context The Context in which this LayoutInflater will create its
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Views; most importantly, this supplies the theme from which the default
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * values for their attributes are retrieved.
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected LayoutInflater(Context context) {
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new LayoutInflater instance that is a copy of an existing
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater, optionally with its Context changed.  For use in
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementing {@link #cloneInContext}.
195579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param original The original LayoutInflater to copy.
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param newContext The new Context to use.
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected LayoutInflater(LayoutInflater original, Context newContext) {
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = newContext;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFactory = original.mFactory;
202625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        mFactory2 = original.mFactory2;
203420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn        mPrivateFactory = original.mPrivateFactory;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilter = original.mFilter;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
206579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Obtains the LayoutInflater from the given context.
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static LayoutInflater from(Context context) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LayoutInflater LayoutInflater =
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LayoutInflater == null) {
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new AssertionError("LayoutInflater not found.");
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return LayoutInflater;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a copy of the existing LayoutInflater object, with the copy
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pointing to a different Context than the original.  This is used by
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ContextThemeWrapper} to create a new LayoutInflater to go along
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with the new Context theme.
224579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param newContext The new Context to associate with the new LayoutInflater.
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * May be the same as the original Context if desired.
227579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a brand spanking new LayoutInflater object associated with
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the given Context.
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract LayoutInflater cloneInContext(Context newContext);
232579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the context we are running in, for access to resources, class
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * loader, etc.
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Context getContext() {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContext;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
242625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Return the current {@link Factory} (or null). This is called on each element
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * name. If the factory returns a View, add that to the hierarchy. If it
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returns null, proceed to call onCreateView(name).
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final Factory getFactory() {
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFactory;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
251625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Return the current {@link Factory2}.  Returns null if no factory is set
252625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * or the set factory does not implement the {@link Factory2} interface.
253625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * This is called on each element
254625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * name. If the factory returns a View, add that to the hierarchy. If it
255625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * returns null, proceed to call onCreateView(name).
256625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
257625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public final Factory2 getFactory2() {
258625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        return mFactory2;
259625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
260625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
261625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Attach a custom Factory interface for creating views while using
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this LayoutInflater.  This must not be null, and can only be set once;
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after setting, you can not change the factory.  This is
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called on each element name as the xml is parsed. If the factory returns
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a View, that is added to the hierarchy. If it returns null, the next
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * factory default {@link #onCreateView} method is called.
268579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If you have an existing
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater and want to add your own factory to it, use
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #cloneInContext} to clone the existing instance and then you
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can use this function (once) on the returned new instance.  This will
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * merge your own factory with whatever factory the original instance is
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * using.
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFactory(Factory factory) {
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFactorySet) {
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (factory == null) {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new NullPointerException("Given factory can not be null");
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFactorySet = true;
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFactory == null) {
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFactory = factory;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
287625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mFactory = new FactoryMerger(factory, null, mFactory, mFactory2);
288625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
289625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
290625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
291625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
292625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Like {@link #setFactory}, but allows you to set a {@link Factory2}
293625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * interface.
294625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
295625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public void setFactory2(Factory2 factory) {
296625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (mFactorySet) {
297625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
298625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
299625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (factory == null) {
300625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throw new NullPointerException("Given factory can not be null");
301625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
302625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        mFactorySet = true;
303625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (mFactory == null) {
304625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mFactory = mFactory2 = factory;
305625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        } else {
306625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mFactory = new FactoryMerger(factory, factory, mFactory, mFactory2);
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
311420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn     * @hide for use by framework
312420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn     */
313420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    public void setPrivateFactory(Factory2 factory) {
314420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn        mPrivateFactory = factory;
315420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    }
316420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn
317420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    /**
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The {@link Filter} currently used by this LayoutInflater to restrict the set of Views
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that are allowed to be inflated.
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Filter getFilter() {
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFilter;
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
324579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * throw an {@link InflateException}. This filter will replace any previous filter set on this
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater.
330579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param filter The Filter which restricts the set of Views that are allowed to be inflated.
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        This filter will replace any previous filter set on this LayoutInflater.
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFilter(Filter filter) {
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilter = filter;
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (filter != null) {
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFilterMap = new HashMap<String, Boolean>();
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml resource. Throws
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
344579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resource ID for an XML layout resource to load (e.g.,
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <code>R.layout.main_page</code>)
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy.
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied,
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         this is the root View; otherwise it is the root of the inflated
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         XML file.
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(int resource, ViewGroup root) {
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return inflate(resource, root, root != null);
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml node. Throws
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error. *
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * reasons, view inflation relies heavily on pre-processing of XML files
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that is done at build time. Therefore, it is not currently possible to
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
364579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parser XML dom node containing the description of the view
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy.
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy.
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied,
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         this is the root View; otherwise it is the root of the inflated
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         XML file.
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(XmlPullParser parser, ViewGroup root) {
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return inflate(parser, root, root != null);
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml resource. Throws
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
379579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resource ID for an XML layout resource to load (e.g.,
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <code>R.layout.main_page</code>)
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy (if
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <em>attachToRoot</em> is true), or else simply an object that
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        provides a set of LayoutParams values for root of the returned
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy (if <em>attachToRoot</em> is false.)
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attachToRoot Whether the inflated hierarchy should be attached to
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        the root parameter? If false, root is only used to create the
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        correct subclass of LayoutParams for the root view in the XML.
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied and
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         attachToRoot is true, this is root; otherwise it is the root of
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the inflated XML file.
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG) System.out.println("INFLATING from resource: " + resource);
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        XmlResourceParser parser = getContext().getResources().getLayout(resource);
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return inflate(parser, root, attachToRoot);
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            parser.close();
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified XML node. Throws
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * reasons, view inflation relies heavily on pre-processing of XML files
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that is done at build time. Therefore, it is not currently possible to
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
411579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parser XML dom node containing the description of the view
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy.
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy (if
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <em>attachToRoot</em> is true), or else simply an object that
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        provides a set of LayoutParams values for root of the returned
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy (if <em>attachToRoot</em> is false.)
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attachToRoot Whether the inflated hierarchy should be attached to
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        the root parameter? If false, root is only used to create the
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        correct subclass of LayoutParams for the root view in the XML.
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied and
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         attachToRoot is true, this is root; otherwise it is the root of
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the inflated XML file.
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mConstructorArgs) {
42709f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");
42809f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final AttributeSet attrs = Xml.asAttributeSet(parser);
4309dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn            Context lastContext = (Context)mConstructorArgs[0];
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstructorArgs[0] = mContext;
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View result = root;
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Look for the root node.
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int type;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while ((type = parser.next()) != XmlPullParser.START_TAG &&
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        type != XmlPullParser.END_DOCUMENT) {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Empty
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type != XmlPullParser.START_TAG) {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException(parser.getPositionDescription()
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + ": No start tag found!");
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final String name = parser.getName();
448579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) {
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("**************************");
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("Creating root view: "
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + name);
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("**************************");
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (TAG_MERGE.equals(name)) {
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root == null || !attachToRoot) {
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        throw new InflateException("<merge /> can be used only with a valid "
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                + "ViewGroup root and attachToRoot=true");
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4629295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy                    rInflate(parser, root, attrs, false);
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Temp is the root view that was found in the xml
4659c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    View temp;
4669c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    if (TAG_1995.equals(name)) {
4679c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        temp = new BlinkLayout(mContext, attrs);
4689c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    } else {
4699c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        temp = createViewFromTag(root, name, attrs);
4709c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    }
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ViewGroup.LayoutParams params = null;
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root != null) {
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (DEBUG) {
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.out.println("Creating params from root: " +
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    root);
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Create layout params that match root, if supplied
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        params = root.generateLayoutParams(attrs);
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!attachToRoot) {
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // Set the layout params for temp if we are not
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // attaching. (If we are, we use addView, below)
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            temp.setLayoutParams(params);
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (DEBUG) {
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        System.out.println("-----> start inflating children");
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Inflate all children under temp
4929295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy                    rInflate(parser, temp, attrs, true);
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (DEBUG) {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        System.out.println("-----> done inflating children");
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We are supposed to attach all the views we found (int temp)
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to root. Do that now.
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root != null && attachToRoot) {
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        root.addView(temp, params);
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Decide whether to return the root that was passed in or the
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // top view found in xml.
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root == null || !attachToRoot) {
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        result = temp;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (XmlPullParserException e) {
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InflateException ex = new InflateException(e.getMessage());
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ex.initCause(e);
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw ex;
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InflateException ex = new InflateException(
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        parser.getPositionDescription()
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": " + e.getMessage());
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ex.initCause(e);
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw ex;
5209dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn            } finally {
5219dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                // Don't retain static reference on context.
5229dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                mConstructorArgs[0] = lastContext;
5239dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                mConstructorArgs[1] = null;
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
52609f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
52709f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return result;
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Low-level function for instantiating a view by name. This attempts to
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instantiate a view class of the given <var>name</var> found in this
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater's ClassLoader.
536579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * There are two things that can happen in an error case: either the
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * exception describing the error will be thrown, or a null will be
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned. You must deal with both possibilities -- the former will happen
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the first time createView() is called for a class of a particular name,
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the latter every time there-after for that class name.
543579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param name The full name of the class to be instantiated.
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attrs The XML attributes supplied for this instance.
546579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
5473030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne     * @return View The newly instantiated view, or null.
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final View createView(String name, String prefix, AttributeSet attrs)
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ClassNotFoundException, InflateException {
5513030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        Constructor<? extends View> constructor = sConstructorMap.get(name);
5523030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        Class<? extends View> clazz = null;
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
55509f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy            Trace.traceBegin(Trace.TRACE_TAG_VIEW, name);
55609f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (constructor == null) {
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Class not found in the cache, see if it's real, and try to add it
559d03b880836bcc4fae83a95458e0709cd45aa6313Romain Guy                clazz = mContext.getClassLoader().loadClass(
5603030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                        prefix != null ? (prefix + name) : name).asSubclass(View.class);
561579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFilter != null && clazz != null) {
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean allowed = mFilter.onLoadClass(clazz);
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!allowed) {
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        failNotAllowed(name, prefix, attrs);
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                constructor = clazz.getConstructor(mConstructorSignature);
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sConstructorMap.put(name, constructor);
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If we have a filter, apply it to cached constructor
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFilter != null) {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Have we seen this name before?
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Boolean allowedState = mFilterMap.get(name);
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (allowedState == null) {
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // New class -- remember whether it is allowed
577d03b880836bcc4fae83a95458e0709cd45aa6313Romain Guy                        clazz = mContext.getClassLoader().loadClass(
5783030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                                prefix != null ? (prefix + name) : name).asSubclass(View.class);
579579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mFilterMap.put(name, allowed);
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!allowed) {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            failNotAllowed(name, prefix, attrs);
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (allowedState.equals(Boolean.FALSE)) {
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        failNotAllowed(name, prefix, attrs);
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Object[] args = mConstructorArgs;
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            args[1] = attrs;
593b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey
594b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            final View view = constructor.newInstance(args);
595b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            if (view instanceof ViewStub) {
596b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey                // always use ourselves when inflating ViewStub later
597b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey                final ViewStub viewStub = (ViewStub) view;
598b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey                viewStub.setLayoutInflater(this);
599b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            }
600b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            return view;
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (NoSuchMethodException e) {
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class "
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + (prefix != null ? (prefix + name) : name));
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6093030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        } catch (ClassCastException e) {
6103030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            // If loaded class is not a View subclass
6113030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            InflateException ie = new InflateException(attrs.getPositionDescription()
6123030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                    + ": Class is not a View "
6133030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                    + (prefix != null ? (prefix + name) : name));
6143030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            ie.initCause(e);
6153030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            throw ie;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (ClassNotFoundException e) {
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If loadClass fails, we should propagate the exception.
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class "
622d03b880836bcc4fae83a95458e0709cd45aa6313Romain Guy                    + (clazz == null ? "<unknown>" : clazz.getName()));
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
62509f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy        } finally {
62609f7b93a184d12e5ed584206d903982b3e0915e5Romain Guy            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6313030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne     * Throw an exception because the specified class is not allowed to be inflated.
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
6349c1223a71397b565f38015c07cae57a5015a6500Romain Guy        throw new InflateException(attrs.getPositionDescription()
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + ": Class not allowed to be inflated "
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + (prefix != null ? (prefix + name) : name));
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This routine is responsible for creating the correct subclass of View
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * given the xml element name. Override it to handle custom view objects. If
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * you override this in your subclass be sure to call through to
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * super.onCreateView(name) for names you do not recognize.
644579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param name The fully qualified class name of the View to be create.
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attrs An AttributeSet of attributes to apply to the View.
647579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke     *
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return View The View created.
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected View onCreateView(String name, AttributeSet attrs)
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ClassNotFoundException {
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return createView(name, "android.view.", attrs);
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
655625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
656625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Version of {@link #onCreateView(String, AttributeSet)} that also
657430742f09063574271e6c4091de13b9b9e762514Chet Haase     * takes the future parent of the view being constructed.  The default
658625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * implementation simply calls {@link #onCreateView(String, AttributeSet)}.
659625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     *
660625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param parent The future parent of the returned view.  <em>Note that
661625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * this may be null.</em>
662625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param name The fully qualified class name of the View to be create.
663625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param attrs An AttributeSet of attributes to apply to the View.
664625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     *
665625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @return View The View created.
666625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
667625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    protected View onCreateView(View parent, String name, AttributeSet attrs)
668625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throws ClassNotFoundException {
669625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        return onCreateView(name, attrs);
670625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
671625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * default visibility so the BridgeInflater can override it.
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
675625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    View createViewFromTag(View parent, String name, AttributeSet attrs) {
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (name.equals("view")) {
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            name = attrs.getAttributeValue(null, "class");
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG) System.out.println("******** Creating view: " + name);
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
683625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            View view;
684625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            if (mFactory2 != null) view = mFactory2.onCreateView(parent, name, mContext, attrs);
685625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            else if (mFactory != null) view = mFactory.onCreateView(name, mContext, attrs);
686625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            else view = null;
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
688420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn            if (view == null && mPrivateFactory != null) {
689420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn                view = mPrivateFactory.onCreateView(parent, name, mContext, attrs);
690420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn            }
691579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (view == null) {
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (-1 == name.indexOf('.')) {
694625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                    view = onCreateView(parent, name, attrs);
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    view = createView(name, null, attrs);
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) System.out.println("Created view is: " + view);
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return view;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (InflateException e) {
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (ClassNotFoundException e) {
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class " + name);
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class " + name);
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Recursive method used to descend down the xml hierarchy and instantiate
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * views, instantiate their children, and then call onFinishInflate().
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7247f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs,
7259295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy            boolean finishInflate) throws XmlPullParserException, IOException {
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int depth = parser.getDepth();
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (((type = parser.next()) != XmlPullParser.END_TAG ||
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type != XmlPullParser.START_TAG) {
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String name = parser.getName();
738579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (TAG_REQUEST_FOCUS.equals(name)) {
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parseRequestFocus(parser, parent);
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (TAG_INCLUDE.equals(name)) {
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (parser.getDepth() == 0) {
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException("<include /> cannot be the root element");
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parseInclude(parser, parent, attrs);
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (TAG_MERGE.equals(name)) {
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new InflateException("<merge /> must be the root element");
7489c1223a71397b565f38015c07cae57a5015a6500Romain Guy            } else if (TAG_1995.equals(name)) {
7499c1223a71397b565f38015c07cae57a5015a6500Romain Guy                final View view = new BlinkLayout(mContext, attrs);
7509c1223a71397b565f38015c07cae57a5015a6500Romain Guy                final ViewGroup viewGroup = (ViewGroup) parent;
7519c1223a71397b565f38015c07cae57a5015a6500Romain Guy                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
7529c1223a71397b565f38015c07cae57a5015a6500Romain Guy                rInflate(parser, view, attrs, true);
753579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                viewGroup.addView(view, params);
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
755625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                final View view = createViewFromTag(parent, name, attrs);
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ViewGroup viewGroup = (ViewGroup) parent;
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
7589295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy                rInflate(parser, view, attrs, true);
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                viewGroup.addView(view, params);
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7639295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy        if (finishInflate) parent.onFinishInflate();
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void parseRequestFocus(XmlPullParser parser, View parent)
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        parent.requestFocus();
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currentDepth = parser.getDepth();
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (((type = parser.next()) != XmlPullParser.END_TAG ||
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Empty
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void parseInclude(XmlPullParser parser, View parent, AttributeSet attrs)
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (parent instanceof ViewGroup) {
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int layout = attrs.getAttributeResourceValue(null, "layout", 0);
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (layout == 0) {
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final String value = attrs.getAttributeValue(null, "layout");
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value == null) {
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException("You must specifiy a layout in the"
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + " include tag: <include layout=\"@layout/layoutID\" />");
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException("You must specifiy a valid layout "
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + "reference. The layout ID " + value + " is not valid.");
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final XmlResourceParser childParser =
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        getContext().getResources().getLayout(layout);
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    while ((type = childParser.next()) != XmlPullParser.START_TAG &&
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            type != XmlPullParser.END_DOCUMENT) {
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Empty.
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (type != XmlPullParser.START_TAG) {
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        throw new InflateException(childParser.getPositionDescription() +
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                ": No start tag found!");
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final String childName = childParser.getName();
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (TAG_MERGE.equals(childName)) {
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Inflate all children.
8149295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy                        rInflate(childParser, parent, childAttrs, false);
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
816625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                        final View view = createViewFromTag(parent, childName, childAttrs);
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final ViewGroup group = (ViewGroup) parent;
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We try to load the layout params set in the <include /> tag. If
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // they don't exist, we will rely on the layout params set in the
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // included XML file.
822579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        // During a layoutparams generation, a runtime exception is thrown
823579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        // if either layout_width or layout_height is missing. We catch
824579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        // this exception and set localParams accordingly: true means we
825579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        // successfully loaded layout params from the <include /> tag,
826579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        // false means we need to rely on the included layout params.
827579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        ViewGroup.LayoutParams params = null;
828579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        try {
829579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                            params = group.generateLayoutParams(attrs);
830579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        } catch (RuntimeException e) {
831579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                            params = group.generateLayoutParams(childAttrs);
832579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        } finally {
833579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                            if (params != null) {
834579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                                view.setLayoutParams(params);
835579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                            }
836579e14016c4a972e70cd2bd0c6d89bbd7e9e941cDave Burke                        }
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Inflate all children.
8399295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy                        rInflate(childParser, view, childAttrs, true);
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Attempt to override the included layout's android:id with the
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // one set on the <include /> tag itself.
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        TypedArray a = mContext.obtainStyledAttributes(attrs,
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            com.android.internal.R.styleable.View, 0, 0);
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int id = a.getResourceId(com.android.internal.R.styleable.View_id, View.NO_ID);
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // While we're at it, let's try to override android:visibility.
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int visibility = a.getInt(com.android.internal.R.styleable.View_visibility, -1);
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        a.recycle();
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (id != View.NO_ID) {
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            view.setId(id);
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        switch (visibility) {
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 0:
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.VISIBLE);
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 1:
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.INVISIBLE);
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 2:
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.GONE);
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        group.addView(view);
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } finally {
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childParser.close();
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new InflateException("<include /> can only be used inside of a ViewGroup");
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currentDepth = parser.getDepth();
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (((type = parser.next()) != XmlPullParser.END_TAG ||
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Empty
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8819c1223a71397b565f38015c07cae57a5015a6500Romain Guy    }
8829c1223a71397b565f38015c07cae57a5015a6500Romain Guy
8839c1223a71397b565f38015c07cae57a5015a6500Romain Guy    private static class BlinkLayout extends FrameLayout {
8849c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private static final int MESSAGE_BLINK = 0x42;
8859c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private static final int BLINK_DELAY = 500;
8869c1223a71397b565f38015c07cae57a5015a6500Romain Guy
8879c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private boolean mBlink;
8889c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private boolean mBlinkState;
8899c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private final Handler mHandler;
8909c1223a71397b565f38015c07cae57a5015a6500Romain Guy
8919c1223a71397b565f38015c07cae57a5015a6500Romain Guy        public BlinkLayout(Context context, AttributeSet attrs) {
8929c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super(context, attrs);
8939c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler = new Handler(new Handler.Callback() {
8949c1223a71397b565f38015c07cae57a5015a6500Romain Guy                @Override
8959c1223a71397b565f38015c07cae57a5015a6500Romain Guy                public boolean handleMessage(Message msg) {
8969c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    if (msg.what == MESSAGE_BLINK) {
8979c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        if (mBlink) {
8989c1223a71397b565f38015c07cae57a5015a6500Romain Guy                            mBlinkState = !mBlinkState;
8999c1223a71397b565f38015c07cae57a5015a6500Romain Guy                            makeBlink();
9009c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        }
9019c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        invalidate();
9029c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        return true;
9039c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    }
9049c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    return false;
9059c1223a71397b565f38015c07cae57a5015a6500Romain Guy                }
9069c1223a71397b565f38015c07cae57a5015a6500Romain Guy            });
9079c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
9089c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9099c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private void makeBlink() {
9109c1223a71397b565f38015c07cae57a5015a6500Romain Guy            Message message = mHandler.obtainMessage(MESSAGE_BLINK);
9119c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler.sendMessageDelayed(message, BLINK_DELAY);
9129c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
9139c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9149c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
9159c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void onAttachedToWindow() {
9169c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super.onAttachedToWindow();
9179c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9189c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlink = true;
9199c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlinkState = true;
9209c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9219c1223a71397b565f38015c07cae57a5015a6500Romain Guy            makeBlink();
9229c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
9239c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9249c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
9259c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void onDetachedFromWindow() {
9269c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super.onDetachedFromWindow();
9279c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9289c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlink = false;
9299c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlinkState = true;
9309c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9319c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler.removeMessages(MESSAGE_BLINK);
9329c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
9339c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9349c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
9359c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void dispatchDraw(Canvas canvas) {
9369c1223a71397b565f38015c07cae57a5015a6500Romain Guy            if (mBlinkState) {
9379c1223a71397b565f38015c07cae57a5015a6500Romain Guy                super.dispatchDraw(canvas);
9389c1223a71397b565f38015c07cae57a5015a6500Romain Guy            }
9399c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
9409c1223a71397b565f38015c07cae57a5015a6500Romain Guy    }
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
942