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;
229c1223a71397b565f38015c07cae57a5015a6500Romain Guyimport android.widget.FrameLayout;
233030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport org.xmlpull.v1.XmlPullParser;
243030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunneimport org.xmlpull.v1.XmlPullParserException;
253030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.XmlResourceParser;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Xml;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Constructor;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3793dc642eaf48e3db58c4929df26283fbc5fd663fScott Main * Instantiates a layout XML file into its corresponding {@link android.view.View}
3893dc642eaf48e3db58c4929df26283fbc5fd663fScott Main * objects. It is never used directly. Instead, use
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.app.Activity#getLayoutInflater()} or
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Context#getSystemService} to retrieve a standard LayoutInflater instance
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that is already hooked up to the current context and correctly configured
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for the device you are running on.  For example:
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
45bd6fda11d287ba8ac749e06053dc9488653d1471Christian Mehlmauer *      (Context.LAYOUT_INFLATER_SERVICE);</pre>
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To create a new LayoutInflater with an additional {@link Factory} for your
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * own views, you can use {@link #cloneInContext} to clone an existing
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ViewFactory, and then call {@link #setFactory} on it to include your
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Factory.
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For performance reasons, view inflation relies heavily on pre-processing of
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * XML files that is done at build time. Therefore, it is not currently possible
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it only works with an XmlPullParser returned from a compiled resource
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (R.<em>something</em> file.)
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see Context#getSystemService
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class LayoutInflater {
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final boolean DEBUG = false;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This field should be made private, so it is hidden from the SDK.
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected final Context mContext;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these are optional, set by the caller
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mFactorySet;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Factory mFactory;
74625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    private Factory2 mFactory2;
75420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    private Factory2 mPrivateFactory;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Filter mFilter;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
787f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    final Object[] mConstructorArgs = new Object[2];
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
807f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    static final Class<?>[] mConstructorSignature = new Class[] {
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Context.class, AttributeSet.class};
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
833030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne    private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
843030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            new HashMap<String, Constructor<? extends View>>();
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String, Boolean> mFilterMap;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_MERGE = "merge";
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_INCLUDE = "include";
909c1223a71397b565f38015c07cae57a5015a6500Romain Guy    private static final String TAG_1995 = "blink";
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG_REQUEST_FOCUS = "requestFocus";
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to be inflated.
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Filter {
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Hook to allow clients of the LayoutInflater to restrict the set of Views
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * that are allowed to be inflated.
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param clazz The class object for the View that is about to be inflated
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return True if this class is allowed to be inflated, or false otherwise
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
107e6ac8b9aade9443ab8456c8f7a47cdfba3b70266Gilles Debunne        @SuppressWarnings("unchecked")
108e6ac8b9aade9443ab8456c8f7a47cdfba3b70266Gilles Debunne        boolean onLoadClass(Class clazz);
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Factory {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Hook you can supply that is called when inflating from a LayoutInflater.
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * You can use this to customize the tag names available in your XML
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * layout files.
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note that it is good practice to prefix these custom names with your
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * package (i.e., com.coolcompany.apps) to avoid conflicts with system
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * names.
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param name Tag name to be inflated.
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param context The context the view is being created in.
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param attrs Inflation attributes as specified in XML file.
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return View Newly created view. Return null for the default
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *         behavior.
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View onCreateView(String name, Context context, AttributeSet attrs);
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
132625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public interface Factory2 extends Factory {
133625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        /**
134625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * Version of {@link #onCreateView(String, Context, AttributeSet)}
135625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * that also supplies the parent that the view created view will be
136625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * placed in.
137625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *
138625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param parent The parent that the created view will be placed
139625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * in; <em>note that this may be null</em>.
140625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param name Tag name to be inflated.
141625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param context The context the view is being created in.
142625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @param attrs Inflation attributes as specified in XML file.
143625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *
144625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         * @return View Newly created view. Return null for the default
145625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         *         behavior.
146625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn         */
147625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        public View onCreateView(View parent, String name, Context context, AttributeSet attrs);
148625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
149625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
150625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    private static class FactoryMerger implements Factory2 {
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final Factory mF1, mF2;
152625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        private final Factory2 mF12, mF22;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
154625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mF1 = f1;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mF2 = f2;
157625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mF12 = f12;
158625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mF22 = f22;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View onCreateView(String name, Context context, AttributeSet attrs) {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View v = mF1.onCreateView(name, context, attrs);
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (v != null) return v;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mF2.onCreateView(name, context, attrs);
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
166625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
167625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
168625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            View v = mF12 != null ? mF12.onCreateView(parent, name, context, attrs)
169625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                    : mF1.onCreateView(name, context, attrs);
170625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            if (v != null) return v;
171625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            return mF22 != null ? mF22.onCreateView(parent, name, context, attrs)
172625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                    : mF2.onCreateView(name, context, attrs);
173625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new LayoutInflater instance associated with a particular Context.
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Applications will almost always want to use
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link Context#getSystemService Context.getSystemService()} to retrieve
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context The Context in which this LayoutInflater will create its
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Views; most importantly, this supplies the theme from which the default
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * values for their attributes are retrieved.
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected LayoutInflater(Context context) {
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new LayoutInflater instance that is a copy of an existing
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater, optionally with its Context changed.  For use in
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementing {@link #cloneInContext}.
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param original The original LayoutInflater to copy.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param newContext The new Context to use.
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected LayoutInflater(LayoutInflater original, Context newContext) {
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = newContext;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFactory = original.mFactory;
201625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        mFactory2 = original.mFactory2;
202420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn        mPrivateFactory = original.mPrivateFactory;
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilter = original.mFilter;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Obtains the LayoutInflater from the given context.
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static LayoutInflater from(Context context) {
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LayoutInflater LayoutInflater =
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LayoutInflater == null) {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new AssertionError("LayoutInflater not found.");
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return LayoutInflater;
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a copy of the existing LayoutInflater object, with the copy
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pointing to a different Context than the original.  This is used by
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ContextThemeWrapper} to create a new LayoutInflater to go along
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with the new Context theme.
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param newContext The new Context to associate with the new LayoutInflater.
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * May be the same as the original Context if desired.
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a brand spanking new LayoutInflater object associated with
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the given Context.
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract LayoutInflater cloneInContext(Context newContext);
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the context we are running in, for access to resources, class
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * loader, etc.
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Context getContext() {
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContext;
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
241625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Return the current {@link Factory} (or null). This is called on each element
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * name. If the factory returns a View, add that to the hierarchy. If it
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returns null, proceed to call onCreateView(name).
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final Factory getFactory() {
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFactory;
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
250625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Return the current {@link Factory2}.  Returns null if no factory is set
251625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * or the set factory does not implement the {@link Factory2} interface.
252625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * This is called on each element
253625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * name. If the factory returns a View, add that to the hierarchy. If it
254625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * returns null, proceed to call onCreateView(name).
255625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
256625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public final Factory2 getFactory2() {
257625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        return mFactory2;
258625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
259625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
260625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Attach a custom Factory interface for creating views while using
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this LayoutInflater.  This must not be null, and can only be set once;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after setting, you can not change the factory.  This is
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called on each element name as the xml is parsed. If the factory returns
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a View, that is added to the hierarchy. If it returns null, the next
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * factory default {@link #onCreateView} method is called.
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If you have an existing
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater and want to add your own factory to it, use
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #cloneInContext} to clone the existing instance and then you
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can use this function (once) on the returned new instance.  This will
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * merge your own factory with whatever factory the original instance is
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * using.
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFactory(Factory factory) {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFactorySet) {
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (factory == null) {
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new NullPointerException("Given factory can not be null");
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFactorySet = true;
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFactory == null) {
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFactory = factory;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
286625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mFactory = new FactoryMerger(factory, null, mFactory, mFactory2);
287625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
288625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
289625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
290625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
291625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Like {@link #setFactory}, but allows you to set a {@link Factory2}
292625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * interface.
293625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
294625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    public void setFactory2(Factory2 factory) {
295625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (mFactorySet) {
296625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
297625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
298625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (factory == null) {
299625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throw new NullPointerException("Given factory can not be null");
300625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        }
301625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        mFactorySet = true;
302625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        if (mFactory == null) {
303625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mFactory = mFactory2 = factory;
304625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        } else {
305625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            mFactory = new FactoryMerger(factory, factory, mFactory, mFactory2);
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
310420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn     * @hide for use by framework
311420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn     */
312420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    public void setPrivateFactory(Factory2 factory) {
313420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn        mPrivateFactory = factory;
314420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    }
315420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn
316420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn    /**
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The {@link Filter} currently used by this LayoutInflater to restrict the set of Views
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that are allowed to be inflated.
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Filter getFilter() {
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFilter;
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * throw an {@link InflateException}. This filter will replace any previous filter set on this
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater.
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param filter The Filter which restricts the set of Views that are allowed to be inflated.
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        This filter will replace any previous filter set on this LayoutInflater.
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFilter(Filter filter) {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilter = filter;
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (filter != null) {
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFilterMap = new HashMap<String, Boolean>();
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml resource. Throws
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resource ID for an XML layout resource to load (e.g.,
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <code>R.layout.main_page</code>)
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy.
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied,
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         this is the root View; otherwise it is the root of the inflated
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         XML file.
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(int resource, ViewGroup root) {
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return inflate(resource, root, root != null);
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml node. Throws
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error. *
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * reasons, view inflation relies heavily on pre-processing of XML files
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that is done at build time. Therefore, it is not currently possible to
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parser XML dom node containing the description of the view
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy.
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy.
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied,
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         this is the root View; otherwise it is the root of the inflated
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         XML file.
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(XmlPullParser parser, ViewGroup root) {
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return inflate(parser, root, root != null);
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified xml resource. Throws
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resource ID for an XML layout resource to load (e.g.,
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <code>R.layout.main_page</code>)
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy (if
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <em>attachToRoot</em> is true), or else simply an object that
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        provides a set of LayoutParams values for root of the returned
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy (if <em>attachToRoot</em> is false.)
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attachToRoot Whether the inflated hierarchy should be attached to
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        the root parameter? If false, root is only used to create the
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        correct subclass of LayoutParams for the root view in the XML.
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied and
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         attachToRoot is true, this is root; otherwise it is the root of
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the inflated XML file.
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG) System.out.println("INFLATING from resource: " + resource);
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        XmlResourceParser parser = getContext().getResources().getLayout(resource);
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return inflate(parser, root, attachToRoot);
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            parser.close();
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflate a new view hierarchy from the specified XML node. Throws
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link InflateException} if there is an error.
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * reasons, view inflation relies heavily on pre-processing of XML files
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that is done at build time. Therefore, it is not currently possible to
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parser XML dom node containing the description of the view
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy.
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param root Optional view to be the parent of the generated hierarchy (if
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        <em>attachToRoot</em> is true), or else simply an object that
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        provides a set of LayoutParams values for root of the returned
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        hierarchy (if <em>attachToRoot</em> is false.)
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attachToRoot Whether the inflated hierarchy should be attached to
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        the root parameter? If false, root is only used to create the
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        correct subclass of LayoutParams for the root view in the XML.
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root View of the inflated hierarchy. If root was supplied and
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         attachToRoot is true, this is root; otherwise it is the root of
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the inflated XML file.
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mConstructorArgs) {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final AttributeSet attrs = Xml.asAttributeSet(parser);
4279dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn            Context lastContext = (Context)mConstructorArgs[0];
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstructorArgs[0] = mContext;
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View result = root;
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Look for the root node.
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int type;
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while ((type = parser.next()) != XmlPullParser.START_TAG &&
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        type != XmlPullParser.END_DOCUMENT) {
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Empty
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type != XmlPullParser.START_TAG) {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException(parser.getPositionDescription()
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + ": No start tag found!");
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final String name = parser.getName();
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) {
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("**************************");
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("Creating root view: "
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + name);
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("**************************");
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (TAG_MERGE.equals(name)) {
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root == null || !attachToRoot) {
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        throw new InflateException("<merge /> can be used only with a valid "
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                + "ViewGroup root and attachToRoot=true");
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4599295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy                    rInflate(parser, root, attrs, false);
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Temp is the root view that was found in the xml
4629c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    View temp;
4639c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    if (TAG_1995.equals(name)) {
4649c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        temp = new BlinkLayout(mContext, attrs);
4659c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    } else {
4669c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        temp = createViewFromTag(root, name, attrs);
4679c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    }
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ViewGroup.LayoutParams params = null;
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root != null) {
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (DEBUG) {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.out.println("Creating params from root: " +
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    root);
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Create layout params that match root, if supplied
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        params = root.generateLayoutParams(attrs);
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!attachToRoot) {
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // Set the layout params for temp if we are not
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // attaching. (If we are, we use addView, below)
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            temp.setLayoutParams(params);
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (DEBUG) {
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        System.out.println("-----> start inflating children");
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Inflate all children under temp
4899295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy                    rInflate(parser, temp, attrs, true);
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (DEBUG) {
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        System.out.println("-----> done inflating children");
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We are supposed to attach all the views we found (int temp)
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to root. Do that now.
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root != null && attachToRoot) {
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        root.addView(temp, params);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Decide whether to return the root that was passed in or the
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // top view found in xml.
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (root == null || !attachToRoot) {
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        result = temp;
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (XmlPullParserException e) {
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InflateException ex = new InflateException(e.getMessage());
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ex.initCause(e);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw ex;
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InflateException ex = new InflateException(
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        parser.getPositionDescription()
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": " + e.getMessage());
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ex.initCause(e);
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw ex;
5179dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn            } finally {
5189dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                // Don't retain static reference on context.
5199dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                mConstructorArgs[0] = lastContext;
5209dae48e3992521f104cde7c916ed1fb5ee1ecb54Dianne Hackborn                mConstructorArgs[1] = null;
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return result;
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Low-level function for instantiating a view by name. This attempts to
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instantiate a view class of the given <var>name</var> found in this
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * LayoutInflater's ClassLoader.
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * There are two things that can happen in an error case: either the
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * exception describing the error will be thrown, or a null will be
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned. You must deal with both possibilities -- the former will happen
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the first time createView() is called for a class of a particular name,
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the latter every time there-after for that class name.
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param name The full name of the class to be instantiated.
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attrs The XML attributes supplied for this instance.
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5423030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne     * @return View The newly instantiated view, or null.
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final View createView(String name, String prefix, AttributeSet attrs)
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ClassNotFoundException, InflateException {
5463030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        Constructor<? extends View> constructor = sConstructorMap.get(name);
5473030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        Class<? extends View> clazz = null;
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (constructor == null) {
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Class not found in the cache, see if it's real, and try to add it
552d03b880836bcc4fae83a95458e0709cd45aa6313Romain Guy                clazz = mContext.getClassLoader().loadClass(
5533030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                        prefix != null ? (prefix + name) : name).asSubclass(View.class);
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFilter != null && clazz != null) {
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean allowed = mFilter.onLoadClass(clazz);
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!allowed) {
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        failNotAllowed(name, prefix, attrs);
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                constructor = clazz.getConstructor(mConstructorSignature);
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sConstructorMap.put(name, constructor);
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If we have a filter, apply it to cached constructor
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFilter != null) {
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Have we seen this name before?
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Boolean allowedState = mFilterMap.get(name);
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (allowedState == null) {
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // New class -- remember whether it is allowed
570d03b880836bcc4fae83a95458e0709cd45aa6313Romain Guy                        clazz = mContext.getClassLoader().loadClass(
5713030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                                prefix != null ? (prefix + name) : name).asSubclass(View.class);
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mFilterMap.put(name, allowed);
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!allowed) {
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            failNotAllowed(name, prefix, attrs);
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (allowedState.equals(Boolean.FALSE)) {
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        failNotAllowed(name, prefix, attrs);
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Object[] args = mConstructorArgs;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            args[1] = attrs;
586b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey
587b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            final View view = constructor.newInstance(args);
588b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            if (view instanceof ViewStub) {
589b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey                // always use ourselves when inflating ViewStub later
590b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey                final ViewStub viewStub = (ViewStub) view;
591b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey                viewStub.setLayoutInflater(this);
592b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            }
593b27b7a152437d6ebb4f2a2700858b69634c00acdJeff Sharkey            return view;
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (NoSuchMethodException e) {
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class "
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + (prefix != null ? (prefix + name) : name));
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6023030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne        } catch (ClassCastException e) {
6033030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            // If loaded class is not a View subclass
6043030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            InflateException ie = new InflateException(attrs.getPositionDescription()
6053030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                    + ": Class is not a View "
6063030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne                    + (prefix != null ? (prefix + name) : name));
6073030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            ie.initCause(e);
6083030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne            throw ie;
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (ClassNotFoundException e) {
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If loadClass fails, we should propagate the exception.
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class "
615d03b880836bcc4fae83a95458e0709cd45aa6313Romain Guy                    + (clazz == null ? "<unknown>" : clazz.getName()));
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6223030193dc179b3010f2dd3bffe9c1dec54da38fcGilles Debunne     * Throw an exception because the specified class is not allowed to be inflated.
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
6259c1223a71397b565f38015c07cae57a5015a6500Romain Guy        throw new InflateException(attrs.getPositionDescription()
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + ": Class not allowed to be inflated "
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + (prefix != null ? (prefix + name) : name));
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This routine is responsible for creating the correct subclass of View
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * given the xml element name. Override it to handle custom view objects. If
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * you override this in your subclass be sure to call through to
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * super.onCreateView(name) for names you do not recognize.
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param name The fully qualified class name of the View to be create.
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param attrs An AttributeSet of attributes to apply to the View.
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return View The View created.
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected View onCreateView(String name, AttributeSet attrs)
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ClassNotFoundException {
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return createView(name, "android.view.", attrs);
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
646625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    /**
647625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * Version of {@link #onCreateView(String, AttributeSet)} that also
648625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * takes the future parent of the view being constructure.  The default
649625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * implementation simply calls {@link #onCreateView(String, AttributeSet)}.
650625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     *
651625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param parent The future parent of the returned view.  <em>Note that
652625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * this may be null.</em>
653625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param name The fully qualified class name of the View to be create.
654625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @param attrs An AttributeSet of attributes to apply to the View.
655625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     *
656625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     * @return View The View created.
657625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn     */
658625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    protected View onCreateView(View parent, String name, AttributeSet attrs)
659625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            throws ClassNotFoundException {
660625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn        return onCreateView(name, attrs);
661625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    }
662625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * default visibility so the BridgeInflater can override it.
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
666625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn    View createViewFromTag(View parent, String name, AttributeSet attrs) {
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (name.equals("view")) {
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            name = attrs.getAttributeValue(null, "class");
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG) System.out.println("******** Creating view: " + name);
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
674625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            View view;
675625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            if (mFactory2 != null) view = mFactory2.onCreateView(parent, name, mContext, attrs);
676625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            else if (mFactory != null) view = mFactory.onCreateView(name, mContext, attrs);
677625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn            else view = null;
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
679420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn            if (view == null && mPrivateFactory != null) {
680420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn                view = mPrivateFactory.onCreateView(parent, name, mContext, attrs);
681420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn            }
682420829ef78c5d86e470fc445279c7c10be6b5dbeDianne Hackborn
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (view == null) {
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (-1 == name.indexOf('.')) {
685625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                    view = onCreateView(parent, name, attrs);
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    view = createView(name, null, attrs);
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG) System.out.println("Created view is: " + view);
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return view;
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (InflateException e) {
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (ClassNotFoundException e) {
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class " + name);
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InflateException ie = new InflateException(attrs.getPositionDescription()
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ": Error inflating class " + name);
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ie.initCause(e);
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw ie;
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Recursive method used to descend down the xml hierarchy and instantiate
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * views, instantiate their children, and then call onFinishInflate().
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7157f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet    void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs,
7169295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy            boolean finishInflate) throws XmlPullParserException, IOException {
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int depth = parser.getDepth();
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (((type = parser.next()) != XmlPullParser.END_TAG ||
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type != XmlPullParser.START_TAG) {
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String name = parser.getName();
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (TAG_REQUEST_FOCUS.equals(name)) {
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parseRequestFocus(parser, parent);
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (TAG_INCLUDE.equals(name)) {
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (parser.getDepth() == 0) {
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException("<include /> cannot be the root element");
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parseInclude(parser, parent, attrs);
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (TAG_MERGE.equals(name)) {
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new InflateException("<merge /> must be the root element");
7399c1223a71397b565f38015c07cae57a5015a6500Romain Guy            } else if (TAG_1995.equals(name)) {
7409c1223a71397b565f38015c07cae57a5015a6500Romain Guy                final View view = new BlinkLayout(mContext, attrs);
7419c1223a71397b565f38015c07cae57a5015a6500Romain Guy                final ViewGroup viewGroup = (ViewGroup) parent;
7429c1223a71397b565f38015c07cae57a5015a6500Romain Guy                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
7439c1223a71397b565f38015c07cae57a5015a6500Romain Guy                rInflate(parser, view, attrs, true);
7449c1223a71397b565f38015c07cae57a5015a6500Romain Guy                viewGroup.addView(view, params);
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
746625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                final View view = createViewFromTag(parent, name, attrs);
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ViewGroup viewGroup = (ViewGroup) parent;
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
7499295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy                rInflate(parser, view, attrs, true);
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                viewGroup.addView(view, params);
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7549295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy        if (finishInflate) parent.onFinishInflate();
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void parseRequestFocus(XmlPullParser parser, View parent)
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        parent.requestFocus();
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currentDepth = parser.getDepth();
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (((type = parser.next()) != XmlPullParser.END_TAG ||
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Empty
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void parseInclude(XmlPullParser parser, View parent, AttributeSet attrs)
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (parent instanceof ViewGroup) {
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int layout = attrs.getAttributeResourceValue(null, "layout", 0);
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (layout == 0) {
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final String value = attrs.getAttributeValue(null, "layout");
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value == null) {
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException("You must specifiy a layout in the"
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + " include tag: <include layout=\"@layout/layoutID\" />");
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new InflateException("You must specifiy a valid layout "
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + "reference. The layout ID " + value + " is not valid.");
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final XmlResourceParser childParser =
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        getContext().getResources().getLayout(layout);
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    while ((type = childParser.next()) != XmlPullParser.START_TAG &&
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            type != XmlPullParser.END_DOCUMENT) {
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Empty.
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (type != XmlPullParser.START_TAG) {
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        throw new InflateException(childParser.getPositionDescription() +
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                ": No start tag found!");
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final String childName = childParser.getName();
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (TAG_MERGE.equals(childName)) {
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Inflate all children.
8059295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy                        rInflate(childParser, parent, childAttrs, false);
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
807625ac271f80777668f832a344486a6fcdc06d0aeDianne Hackborn                        final View view = createViewFromTag(parent, childName, childAttrs);
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final ViewGroup group = (ViewGroup) parent;
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We try to load the layout params set in the <include /> tag. If
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // they don't exist, we will rely on the layout params set in the
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // included XML file.
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // During a layoutparams generation, a runtime exception is thrown
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // if either layout_width or layout_height is missing. We catch
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // this exception and set localParams accordingly: true means we
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // successfully loaded layout params from the <include /> tag,
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // false means we need to rely on the included layout params.
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ViewGroup.LayoutParams params = null;
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            params = group.generateLayoutParams(attrs);
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (RuntimeException e) {
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            params = group.generateLayoutParams(childAttrs);
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } finally {
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (params != null) {
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setLayoutParams(params);
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Inflate all children.
8309295ada0ec89fa7a666be4a2f1006a4b722adf4fRomain Guy                        rInflate(childParser, view, childAttrs, true);
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Attempt to override the included layout's android:id with the
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // one set on the <include /> tag itself.
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        TypedArray a = mContext.obtainStyledAttributes(attrs,
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            com.android.internal.R.styleable.View, 0, 0);
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int id = a.getResourceId(com.android.internal.R.styleable.View_id, View.NO_ID);
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // While we're at it, let's try to override android:visibility.
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int visibility = a.getInt(com.android.internal.R.styleable.View_visibility, -1);
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        a.recycle();
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (id != View.NO_ID) {
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            view.setId(id);
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        switch (visibility) {
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 0:
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.VISIBLE);
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 1:
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.INVISIBLE);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case 2:
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                view.setVisibility(View.GONE);
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        group.addView(view);
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } finally {
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childParser.close();
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new InflateException("<include /> can only be used inside of a ViewGroup");
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currentDepth = parser.getDepth();
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (((type = parser.next()) != XmlPullParser.END_TAG ||
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Empty
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8729c1223a71397b565f38015c07cae57a5015a6500Romain Guy    }
8739c1223a71397b565f38015c07cae57a5015a6500Romain Guy
8749c1223a71397b565f38015c07cae57a5015a6500Romain Guy    private static class BlinkLayout extends FrameLayout {
8759c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private static final int MESSAGE_BLINK = 0x42;
8769c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private static final int BLINK_DELAY = 500;
8779c1223a71397b565f38015c07cae57a5015a6500Romain Guy
8789c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private boolean mBlink;
8799c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private boolean mBlinkState;
8809c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private final Handler mHandler;
8819c1223a71397b565f38015c07cae57a5015a6500Romain Guy
8829c1223a71397b565f38015c07cae57a5015a6500Romain Guy        public BlinkLayout(Context context, AttributeSet attrs) {
8839c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super(context, attrs);
8849c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler = new Handler(new Handler.Callback() {
8859c1223a71397b565f38015c07cae57a5015a6500Romain Guy                @Override
8869c1223a71397b565f38015c07cae57a5015a6500Romain Guy                public boolean handleMessage(Message msg) {
8879c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    if (msg.what == MESSAGE_BLINK) {
8889c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        if (mBlink) {
8899c1223a71397b565f38015c07cae57a5015a6500Romain Guy                            mBlinkState = !mBlinkState;
8909c1223a71397b565f38015c07cae57a5015a6500Romain Guy                            makeBlink();
8919c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        }
8929c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        invalidate();
8939c1223a71397b565f38015c07cae57a5015a6500Romain Guy                        return true;
8949c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    }
8959c1223a71397b565f38015c07cae57a5015a6500Romain Guy                    return false;
8969c1223a71397b565f38015c07cae57a5015a6500Romain Guy                }
8979c1223a71397b565f38015c07cae57a5015a6500Romain Guy            });
8989c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
8999c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9009c1223a71397b565f38015c07cae57a5015a6500Romain Guy        private void makeBlink() {
9019c1223a71397b565f38015c07cae57a5015a6500Romain Guy            Message message = mHandler.obtainMessage(MESSAGE_BLINK);
9029c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler.sendMessageDelayed(message, BLINK_DELAY);
9039c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
9049c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9059c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
9069c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void onAttachedToWindow() {
9079c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super.onAttachedToWindow();
9089c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9099c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlink = true;
9109c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlinkState = true;
9119c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9129c1223a71397b565f38015c07cae57a5015a6500Romain Guy            makeBlink();
9139c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
9149c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9159c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
9169c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void onDetachedFromWindow() {
9179c1223a71397b565f38015c07cae57a5015a6500Romain Guy            super.onDetachedFromWindow();
9189c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9199c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlink = false;
9209c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mBlinkState = true;
9219c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9229c1223a71397b565f38015c07cae57a5015a6500Romain Guy            mHandler.removeMessages(MESSAGE_BLINK);
9239c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
9249c1223a71397b565f38015c07cae57a5015a6500Romain Guy
9259c1223a71397b565f38015c07cae57a5015a6500Romain Guy        @Override
9269c1223a71397b565f38015c07cae57a5015a6500Romain Guy        protected void dispatchDraw(Canvas canvas) {
9279c1223a71397b565f38015c07cae57a5015a6500Romain Guy            if (mBlinkState) {
9289c1223a71397b565f38015c07cae57a5015a6500Romain Guy                super.dispatchDraw(canvas);
9299c1223a71397b565f38015c07cae57a5015a6500Romain Guy            }
9309c1223a71397b565f38015c07cae57a5015a6500Romain Guy        }
9319c1223a71397b565f38015c07cae57a5015a6500Romain Guy    }
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
933