blob: d5e9af4ae21b16a7405d26e683034a8db76e84a3 [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
Mihai Predab6af5332009-04-28 14:21:57 +020026import java.lang.ref.WeakReference;
27
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028/**
29 * A ViewStub is an invisible, zero-sized View that can be used to lazily inflate
30 * layout resources at runtime.
31 *
32 * When a ViewStub is made visible, or when {@link #inflate()} is invoked, the layout resource
33 * is inflated. The ViewStub then replaces itself in its parent with the inflated View or Views.
34 * Therefore, the ViewStub exists in the view hierarchy until {@link #setVisibility(int)} or
35 * {@link #inflate()} is invoked.
36 *
37 * The inflated View is added to the ViewStub's parent with the ViewStub's layout
38 * parameters. Similarly, you can define/override the inflate View's id by using the
39 * ViewStub's inflatedId property. For instance:
40 *
41 * <pre>
42 * &lt;ViewStub android:id="@+id/stub"
43 * android:inflatedId="@+id/subTree"
44 * android:layout="@layout/mySubTree"
45 * android:layout_width="120dip"
46 * android:layout_height="40dip" /&gt;
47 * </pre>
48 *
49 * The ViewStub thus defined can be found using the id "stub." After inflation of
50 * the layout resource "mySubTree," the ViewStub is removed from its parent. The
51 * View created by inflating the layout resource "mySubTree" can be found using the
52 * id "subTree," specified by the inflatedId property. The inflated View is finally
53 * assigned a width of 120dip and a height of 40dip.
54 *
55 * The preferred way to perform the inflation of the layout resource is the following:
56 *
57 * <pre>
58 * ViewStub stub = (ViewStub) findViewById(R.id.stub);
59 * View inflated = stub.inflate();
60 * </pre>
61 *
62 * When {@link #inflate()} is invoked, the ViewStub is replaced by the inflated View
63 * and the inflated View is returned. This lets applications get a reference to the
64 * inflated View without executing an extra findViewById().
65 *
66 * @attr ref android.R.styleable#ViewStub_inflatedId
67 * @attr ref android.R.styleable#ViewStub_layout
68 */
69public final class ViewStub extends View {
70 private int mLayoutResource = 0;
71 private int mInflatedId;
72
Mihai Predab6af5332009-04-28 14:21:57 +020073 private WeakReference<View> mInflatedViewRef;
74
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 private OnInflateListener mInflateListener;
76
77 public ViewStub(Context context) {
78 initialize(context);
79 }
80
81 /**
82 * Creates a new ViewStub with the specified layout resource.
83 *
84 * @param context The application's environment.
85 * @param layoutResource The reference to a layout resource that will be inflated.
86 */
87 public ViewStub(Context context, int layoutResource) {
88 mLayoutResource = layoutResource;
89 initialize(context);
90 }
91
92 public ViewStub(Context context, AttributeSet attrs) {
93 this(context, attrs, 0);
94 }
95
96 @SuppressWarnings({"UnusedDeclaration"})
97 public ViewStub(Context context, AttributeSet attrs, int defStyle) {
98 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ViewStub,
99 defStyle, 0);
100
101 mInflatedId = a.getResourceId(R.styleable.ViewStub_inflatedId, NO_ID);
102 mLayoutResource = a.getResourceId(R.styleable.ViewStub_layout, 0);
103
104 a.recycle();
105
106 a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, defStyle, 0);
107 mID = a.getResourceId(R.styleable.View_id, NO_ID);
108 a.recycle();
109
110 initialize(context);
111 }
112
113 private void initialize(Context context) {
114 mContext = context;
115 setVisibility(GONE);
116 setWillNotDraw(true);
117 }
118
119 /**
120 * Returns the id taken by the inflated view. If the inflated id is
121 * {@link View#NO_ID}, the inflated view keeps its original id.
122 *
123 * @return A positive integer used to identify the inflated view or
124 * {@link #NO_ID} if the inflated view should keep its id.
125 *
126 * @see #setInflatedId(int)
127 * @attr ref android.R.styleable#ViewStub_inflatedId
128 */
129 public int getInflatedId() {
130 return mInflatedId;
131 }
132
133 /**
134 * Defines the id taken by the inflated view. If the inflated id is
135 * {@link View#NO_ID}, the inflated view keeps its original id.
136 *
137 * @param inflatedId A positive integer used to identify the inflated view or
138 * {@link #NO_ID} if the inflated view should keep its id.
139 *
140 * @see #getInflatedId()
141 * @attr ref android.R.styleable#ViewStub_inflatedId
142 */
143 public void setInflatedId(int inflatedId) {
144 mInflatedId = inflatedId;
145 }
146
147 /**
148 * Returns the layout resource that will be used by {@link #setVisibility(int)} or
149 * {@link #inflate()} to replace this StubbedView
150 * in its parent by another view.
151 *
152 * @return The layout resource identifier used to inflate the new View.
153 *
154 * @see #setLayoutResource(int)
155 * @see #setVisibility(int)
156 * @see #inflate()
157 * @attr ref android.R.styleable#ViewStub_layout
158 */
159 public int getLayoutResource() {
160 return mLayoutResource;
161 }
162
163 /**
164 * Specifies the layout resource to inflate when this StubbedView becomes visible or invisible
165 * or when {@link #inflate()} is invoked. The View created by inflating the layout resource is
166 * used to replace this StubbedView in its parent.
167 *
168 * @param layoutResource A valid layout resource identifier (different from 0.)
169 *
170 * @see #getLayoutResource()
171 * @see #setVisibility(int)
172 * @see #inflate()
173 * @attr ref android.R.styleable#ViewStub_layout
174 */
175 public void setLayoutResource(int layoutResource) {
176 mLayoutResource = layoutResource;
177 }
178
179 @Override
180 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
181 setMeasuredDimension(0, 0);
182 }
183
184 @Override
185 public void draw(Canvas canvas) {
186 }
187
188 @Override
189 protected void dispatchDraw(Canvas canvas) {
190 }
191
192 /**
193 * When visibility is set to {@link #VISIBLE} or {@link #INVISIBLE},
194 * {@link #inflate()} is invoked and this StubbedView is replaced in its parent
195 * by the inflated layout resource.
196 *
197 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
198 *
199 * @see #inflate()
200 */
201 @Override
202 public void setVisibility(int visibility) {
Mihai Predab6af5332009-04-28 14:21:57 +0200203 if (mInflatedViewRef != null) {
204 View view = mInflatedViewRef.get();
205 if (view != null) {
206 view.setVisibility(visibility);
207 } else {
208 throw new IllegalStateException("setVisibility called on un-referenced view");
209 }
Adam Powell58acbaf2009-12-15 11:43:34 -0800210 } else {
Mihai Predab6af5332009-04-28 14:21:57 +0200211 super.setVisibility(visibility);
Adam Powell58acbaf2009-12-15 11:43:34 -0800212 if (visibility == VISIBLE || visibility == INVISIBLE) {
213 inflate();
214 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 }
216 }
217
218 /**
219 * Inflates the layout resource identified by {@link #getLayoutResource()}
220 * and replaces this StubbedView in its parent by the inflated layout resource.
221 *
222 * @return The inflated layout resource.
223 *
224 */
225 public View inflate() {
226 final ViewParent viewParent = getParent();
227
228 if (viewParent != null && viewParent instanceof ViewGroup) {
229 if (mLayoutResource != 0) {
230 final ViewGroup parent = (ViewGroup) viewParent;
231 final LayoutInflater factory = LayoutInflater.from(mContext);
232 final View view = factory.inflate(mLayoutResource, parent,
233 false);
234
235 if (mInflatedId != NO_ID) {
236 view.setId(mInflatedId);
237 }
238
239 final int index = parent.indexOfChild(this);
240 parent.removeViewInLayout(this);
241
242 final ViewGroup.LayoutParams layoutParams = getLayoutParams();
243 if (layoutParams != null) {
244 parent.addView(view, index, layoutParams);
245 } else {
246 parent.addView(view, index);
247 }
248
Adam Powell58acbaf2009-12-15 11:43:34 -0800249 mInflatedViewRef = new WeakReference<View>(view);
Mihai Predab6af5332009-04-28 14:21:57 +0200250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 if (mInflateListener != null) {
252 mInflateListener.onInflate(this, view);
253 }
254
255 return view;
256 } else {
257 throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
258 }
259 } else {
260 throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");
261 }
262 }
263
264 /**
265 * Specifies the inflate listener to be notified after this ViewStub successfully
266 * inflated its layout resource.
267 *
268 * @param inflateListener The OnInflateListener to notify of successful inflation.
269 *
270 * @see android.view.ViewStub.OnInflateListener
271 */
272 public void setOnInflateListener(OnInflateListener inflateListener) {
273 mInflateListener = inflateListener;
274 }
275
276 /**
277 * Listener used to receive a notification after a ViewStub has successfully
278 * inflated its layout resource.
279 *
280 * @see android.view.ViewStub#setOnInflateListener(android.view.ViewStub.OnInflateListener)
281 */
282 public static interface OnInflateListener {
283 /**
284 * Invoked after a ViewStub successfully inflated its layout resource.
285 * This method is invoked after the inflated view was added to the
286 * hierarchy but before the layout pass.
287 *
288 * @param stub The ViewStub that initiated the inflation.
289 * @param inflated The inflated View.
290 */
291 void onInflate(ViewStub stub, View inflated);
292 }
293}