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