blob: e159de46bf18fc733da07e9a8d5ae69af6288fdf [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.content.Context;
20import android.content.res.TypedArray;
21import android.graphics.Canvas;
22import android.util.AttributeSet;
23
24import com.android.internal.R;
25
26/**
27 * A ViewStub is an invisible, zero-sized View that can be used to lazily inflate
28 * layout resources at runtime.
29 *
30 * When a ViewStub is made visible, or when {@link #inflate()} is invoked, the layout resource
31 * is inflated. The ViewStub then replaces itself in its parent with the inflated View or Views.
32 * Therefore, the ViewStub exists in the view hierarchy until {@link #setVisibility(int)} or
33 * {@link #inflate()} is invoked.
34 *
35 * The inflated View is added to the ViewStub's parent with the ViewStub's layout
36 * parameters. Similarly, you can define/override the inflate View's id by using the
37 * ViewStub's inflatedId property. For instance:
38 *
39 * <pre>
40 * &lt;ViewStub android:id="@+id/stub"
41 * android:inflatedId="@+id/subTree"
42 * android:layout="@layout/mySubTree"
43 * android:layout_width="120dip"
44 * android:layout_height="40dip" /&gt;
45 * </pre>
46 *
47 * The ViewStub thus defined can be found using the id "stub." After inflation of
48 * the layout resource "mySubTree," the ViewStub is removed from its parent. The
49 * View created by inflating the layout resource "mySubTree" can be found using the
50 * id "subTree," specified by the inflatedId property. The inflated View is finally
51 * assigned a width of 120dip and a height of 40dip.
52 *
53 * The preferred way to perform the inflation of the layout resource is the following:
54 *
55 * <pre>
56 * ViewStub stub = (ViewStub) findViewById(R.id.stub);
57 * View inflated = stub.inflate();
58 * </pre>
59 *
60 * When {@link #inflate()} is invoked, the ViewStub is replaced by the inflated View
61 * and the inflated View is returned. This lets applications get a reference to the
62 * inflated View without executing an extra findViewById().
63 *
64 * @attr ref android.R.styleable#ViewStub_inflatedId
65 * @attr ref android.R.styleable#ViewStub_layout
66 */
67public final class ViewStub extends View {
68 private int mLayoutResource = 0;
69 private int mInflatedId;
70
71 private OnInflateListener mInflateListener;
72
73 public ViewStub(Context context) {
74 initialize(context);
75 }
76
77 /**
78 * Creates a new ViewStub with the specified layout resource.
79 *
80 * @param context The application's environment.
81 * @param layoutResource The reference to a layout resource that will be inflated.
82 */
83 public ViewStub(Context context, int layoutResource) {
84 mLayoutResource = layoutResource;
85 initialize(context);
86 }
87
88 public ViewStub(Context context, AttributeSet attrs) {
89 this(context, attrs, 0);
90 }
91
92 @SuppressWarnings({"UnusedDeclaration"})
93 public ViewStub(Context context, AttributeSet attrs, int defStyle) {
94 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ViewStub,
95 defStyle, 0);
96
97 mInflatedId = a.getResourceId(R.styleable.ViewStub_inflatedId, NO_ID);
98 mLayoutResource = a.getResourceId(R.styleable.ViewStub_layout, 0);
99
100 a.recycle();
101
102 a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, defStyle, 0);
103 mID = a.getResourceId(R.styleable.View_id, NO_ID);
104 a.recycle();
105
106 initialize(context);
107 }
108
109 private void initialize(Context context) {
110 mContext = context;
111 setVisibility(GONE);
112 setWillNotDraw(true);
113 }
114
115 /**
116 * Returns the id taken by the inflated view. If the inflated id is
117 * {@link View#NO_ID}, the inflated view keeps its original id.
118 *
119 * @return A positive integer used to identify the inflated view or
120 * {@link #NO_ID} if the inflated view should keep its id.
121 *
122 * @see #setInflatedId(int)
123 * @attr ref android.R.styleable#ViewStub_inflatedId
124 */
125 public int getInflatedId() {
126 return mInflatedId;
127 }
128
129 /**
130 * Defines the id taken by the inflated view. If the inflated id is
131 * {@link View#NO_ID}, the inflated view keeps its original id.
132 *
133 * @param inflatedId A positive integer used to identify the inflated view or
134 * {@link #NO_ID} if the inflated view should keep its id.
135 *
136 * @see #getInflatedId()
137 * @attr ref android.R.styleable#ViewStub_inflatedId
138 */
139 public void setInflatedId(int inflatedId) {
140 mInflatedId = inflatedId;
141 }
142
143 /**
144 * Returns the layout resource that will be used by {@link #setVisibility(int)} or
145 * {@link #inflate()} to replace this StubbedView
146 * in its parent by another view.
147 *
148 * @return The layout resource identifier used to inflate the new View.
149 *
150 * @see #setLayoutResource(int)
151 * @see #setVisibility(int)
152 * @see #inflate()
153 * @attr ref android.R.styleable#ViewStub_layout
154 */
155 public int getLayoutResource() {
156 return mLayoutResource;
157 }
158
159 /**
160 * Specifies the layout resource to inflate when this StubbedView becomes visible or invisible
161 * or when {@link #inflate()} is invoked. The View created by inflating the layout resource is
162 * used to replace this StubbedView in its parent.
163 *
164 * @param layoutResource A valid layout resource identifier (different from 0.)
165 *
166 * @see #getLayoutResource()
167 * @see #setVisibility(int)
168 * @see #inflate()
169 * @attr ref android.R.styleable#ViewStub_layout
170 */
171 public void setLayoutResource(int layoutResource) {
172 mLayoutResource = layoutResource;
173 }
174
175 @Override
176 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
177 setMeasuredDimension(0, 0);
178 }
179
180 @Override
181 public void draw(Canvas canvas) {
182 }
183
184 @Override
185 protected void dispatchDraw(Canvas canvas) {
186 }
187
188 /**
189 * When visibility is set to {@link #VISIBLE} or {@link #INVISIBLE},
190 * {@link #inflate()} is invoked and this StubbedView is replaced in its parent
191 * by the inflated layout resource.
192 *
193 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
194 *
195 * @see #inflate()
196 */
197 @Override
198 public void setVisibility(int visibility) {
199 super.setVisibility(visibility);
200
201 if (visibility == VISIBLE || visibility == INVISIBLE) {
202 inflate();
203 }
204 }
205
206 /**
207 * Inflates the layout resource identified by {@link #getLayoutResource()}
208 * and replaces this StubbedView in its parent by the inflated layout resource.
209 *
210 * @return The inflated layout resource.
211 *
212 */
213 public View inflate() {
214 final ViewParent viewParent = getParent();
215
216 if (viewParent != null && viewParent instanceof ViewGroup) {
217 if (mLayoutResource != 0) {
218 final ViewGroup parent = (ViewGroup) viewParent;
219 final LayoutInflater factory = LayoutInflater.from(mContext);
220 final View view = factory.inflate(mLayoutResource, parent,
221 false);
222
223 if (mInflatedId != NO_ID) {
224 view.setId(mInflatedId);
225 }
226
227 final int index = parent.indexOfChild(this);
228 parent.removeViewInLayout(this);
229
230 final ViewGroup.LayoutParams layoutParams = getLayoutParams();
231 if (layoutParams != null) {
232 parent.addView(view, index, layoutParams);
233 } else {
234 parent.addView(view, index);
235 }
236
237 if (mInflateListener != null) {
238 mInflateListener.onInflate(this, view);
239 }
240
241 return view;
242 } else {
243 throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
244 }
245 } else {
246 throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");
247 }
248 }
249
250 /**
251 * Specifies the inflate listener to be notified after this ViewStub successfully
252 * inflated its layout resource.
253 *
254 * @param inflateListener The OnInflateListener to notify of successful inflation.
255 *
256 * @see android.view.ViewStub.OnInflateListener
257 */
258 public void setOnInflateListener(OnInflateListener inflateListener) {
259 mInflateListener = inflateListener;
260 }
261
262 /**
263 * Listener used to receive a notification after a ViewStub has successfully
264 * inflated its layout resource.
265 *
266 * @see android.view.ViewStub#setOnInflateListener(android.view.ViewStub.OnInflateListener)
267 */
268 public static interface OnInflateListener {
269 /**
270 * Invoked after a ViewStub successfully inflated its layout resource.
271 * This method is invoked after the inflated view was added to the
272 * hierarchy but before the layout pass.
273 *
274 * @param stub The ViewStub that initiated the inflation.
275 * @param inflated The inflated View.
276 */
277 void onInflate(ViewStub stub, View inflated);
278 }
279}