blob: d68a860a6761dfff412b5b1839ef0844bfc2c9a4 [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;
Jeff Sharkeyb27b7a12012-04-02 21:07:29 -070023import android.widget.RemoteViews.RemoteView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024
25import com.android.internal.R;
26
Mihai Predab6af5332009-04-28 14:21:57 +020027import java.lang.ref.WeakReference;
28
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029/**
30 * A ViewStub is an invisible, zero-sized View that can be used to lazily inflate
31 * layout resources at runtime.
32 *
33 * When a ViewStub is made visible, or when {@link #inflate()} is invoked, the layout resource
34 * is inflated. The ViewStub then replaces itself in its parent with the inflated View or Views.
35 * Therefore, the ViewStub exists in the view hierarchy until {@link #setVisibility(int)} or
36 * {@link #inflate()} is invoked.
37 *
38 * The inflated View is added to the ViewStub's parent with the ViewStub's layout
39 * parameters. Similarly, you can define/override the inflate View's id by using the
40 * ViewStub's inflatedId property. For instance:
41 *
42 * <pre>
43 * &lt;ViewStub android:id="@+id/stub"
44 * android:inflatedId="@+id/subTree"
45 * android:layout="@layout/mySubTree"
46 * android:layout_width="120dip"
47 * android:layout_height="40dip" /&gt;
48 * </pre>
49 *
50 * The ViewStub thus defined can be found using the id "stub." After inflation of
51 * the layout resource "mySubTree," the ViewStub is removed from its parent. The
52 * View created by inflating the layout resource "mySubTree" can be found using the
53 * id "subTree," specified by the inflatedId property. The inflated View is finally
54 * assigned a width of 120dip and a height of 40dip.
55 *
56 * The preferred way to perform the inflation of the layout resource is the following:
57 *
58 * <pre>
59 * ViewStub stub = (ViewStub) findViewById(R.id.stub);
60 * View inflated = stub.inflate();
61 * </pre>
62 *
63 * When {@link #inflate()} is invoked, the ViewStub is replaced by the inflated View
64 * and the inflated View is returned. This lets applications get a reference to the
65 * inflated View without executing an extra findViewById().
66 *
67 * @attr ref android.R.styleable#ViewStub_inflatedId
68 * @attr ref android.R.styleable#ViewStub_layout
69 */
Jeff Sharkeyb27b7a12012-04-02 21:07:29 -070070@RemoteView
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071public final class ViewStub extends View {
72 private int mLayoutResource = 0;
73 private int mInflatedId;
74
Mihai Predab6af5332009-04-28 14:21:57 +020075 private WeakReference<View> mInflatedViewRef;
76
Jeff Sharkeyb27b7a12012-04-02 21:07:29 -070077 private LayoutInflater mInflater;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078 private OnInflateListener mInflateListener;
79
80 public ViewStub(Context context) {
81 initialize(context);
82 }
83
84 /**
85 * Creates a new ViewStub with the specified layout resource.
86 *
87 * @param context The application's environment.
88 * @param layoutResource The reference to a layout resource that will be inflated.
89 */
90 public ViewStub(Context context, int layoutResource) {
91 mLayoutResource = layoutResource;
92 initialize(context);
93 }
94
95 public ViewStub(Context context, AttributeSet attrs) {
96 this(context, attrs, 0);
97 }
98
99 @SuppressWarnings({"UnusedDeclaration"})
Alan Viverette617feb92013-09-09 18:09:13 -0700100 public ViewStub(Context context, AttributeSet attrs, int defStyleAttr) {
101 this(context, attrs, defStyleAttr, 0);
102 }
103
104 public ViewStub(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
105 TypedArray a = context.obtainStyledAttributes(
106 attrs, com.android.internal.R.styleable.ViewStub, defStyleAttr, defStyleRes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107
108 mInflatedId = a.getResourceId(R.styleable.ViewStub_inflatedId, NO_ID);
109 mLayoutResource = a.getResourceId(R.styleable.ViewStub_layout, 0);
110
111 a.recycle();
112
Alan Viverette617feb92013-09-09 18:09:13 -0700113 a = context.obtainStyledAttributes(
114 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 mID = a.getResourceId(R.styleable.View_id, NO_ID);
116 a.recycle();
117
118 initialize(context);
119 }
120
121 private void initialize(Context context) {
122 mContext = context;
123 setVisibility(GONE);
124 setWillNotDraw(true);
125 }
126
127 /**
128 * Returns the id taken by the inflated view. If the inflated id is
129 * {@link View#NO_ID}, the inflated view keeps its original id.
130 *
131 * @return A positive integer used to identify the inflated view or
132 * {@link #NO_ID} if the inflated view should keep its id.
133 *
134 * @see #setInflatedId(int)
135 * @attr ref android.R.styleable#ViewStub_inflatedId
136 */
137 public int getInflatedId() {
138 return mInflatedId;
139 }
140
141 /**
142 * Defines the id taken by the inflated view. If the inflated id is
143 * {@link View#NO_ID}, the inflated view keeps its original id.
144 *
145 * @param inflatedId A positive integer used to identify the inflated view or
146 * {@link #NO_ID} if the inflated view should keep its id.
147 *
148 * @see #getInflatedId()
149 * @attr ref android.R.styleable#ViewStub_inflatedId
150 */
Jeff Sharkeyb27b7a12012-04-02 21:07:29 -0700151 @android.view.RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 public void setInflatedId(int inflatedId) {
153 mInflatedId = inflatedId;
154 }
155
156 /**
157 * Returns the layout resource that will be used by {@link #setVisibility(int)} or
158 * {@link #inflate()} to replace this StubbedView
159 * in its parent by another view.
160 *
161 * @return The layout resource identifier used to inflate the new View.
162 *
163 * @see #setLayoutResource(int)
164 * @see #setVisibility(int)
165 * @see #inflate()
166 * @attr ref android.R.styleable#ViewStub_layout
167 */
168 public int getLayoutResource() {
169 return mLayoutResource;
170 }
171
172 /**
173 * Specifies the layout resource to inflate when this StubbedView becomes visible or invisible
174 * or when {@link #inflate()} is invoked. The View created by inflating the layout resource is
175 * used to replace this StubbedView in its parent.
176 *
177 * @param layoutResource A valid layout resource identifier (different from 0.)
178 *
179 * @see #getLayoutResource()
180 * @see #setVisibility(int)
181 * @see #inflate()
182 * @attr ref android.R.styleable#ViewStub_layout
183 */
Jeff Sharkeyb27b7a12012-04-02 21:07:29 -0700184 @android.view.RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 public void setLayoutResource(int layoutResource) {
186 mLayoutResource = layoutResource;
187 }
188
Jeff Sharkeyb27b7a12012-04-02 21:07:29 -0700189 /**
190 * Set {@link LayoutInflater} to use in {@link #inflate()}, or {@code null}
191 * to use the default.
192 */
193 public void setLayoutInflater(LayoutInflater inflater) {
194 mInflater = inflater;
195 }
196
197 /**
198 * Get current {@link LayoutInflater} used in {@link #inflate()}.
199 */
200 public LayoutInflater getLayoutInflater() {
201 return mInflater;
202 }
203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 @Override
205 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
206 setMeasuredDimension(0, 0);
207 }
208
209 @Override
210 public void draw(Canvas canvas) {
211 }
212
213 @Override
214 protected void dispatchDraw(Canvas canvas) {
215 }
216
217 /**
218 * When visibility is set to {@link #VISIBLE} or {@link #INVISIBLE},
219 * {@link #inflate()} is invoked and this StubbedView is replaced in its parent
Tim Huttf54df842012-11-02 15:13:09 +0000220 * by the inflated layout resource. After that calls to this function are passed
221 * through to the inflated view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 *
223 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
224 *
225 * @see #inflate()
226 */
227 @Override
Jeff Sharkeyb27b7a12012-04-02 21:07:29 -0700228 @android.view.RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 public void setVisibility(int visibility) {
Mihai Predab6af5332009-04-28 14:21:57 +0200230 if (mInflatedViewRef != null) {
231 View view = mInflatedViewRef.get();
232 if (view != null) {
233 view.setVisibility(visibility);
234 } else {
235 throw new IllegalStateException("setVisibility called on un-referenced view");
236 }
Adam Powell58acbaf2009-12-15 11:43:34 -0800237 } else {
Mihai Predab6af5332009-04-28 14:21:57 +0200238 super.setVisibility(visibility);
Adam Powell58acbaf2009-12-15 11:43:34 -0800239 if (visibility == VISIBLE || visibility == INVISIBLE) {
240 inflate();
241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 }
243 }
244
245 /**
246 * Inflates the layout resource identified by {@link #getLayoutResource()}
247 * and replaces this StubbedView in its parent by the inflated layout resource.
248 *
249 * @return The inflated layout resource.
250 *
251 */
252 public View inflate() {
253 final ViewParent viewParent = getParent();
254
255 if (viewParent != null && viewParent instanceof ViewGroup) {
256 if (mLayoutResource != 0) {
257 final ViewGroup parent = (ViewGroup) viewParent;
Jeff Sharkeyb27b7a12012-04-02 21:07:29 -0700258 final LayoutInflater factory;
259 if (mInflater != null) {
260 factory = mInflater;
261 } else {
262 factory = LayoutInflater.from(mContext);
263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 final View view = factory.inflate(mLayoutResource, parent,
265 false);
266
267 if (mInflatedId != NO_ID) {
268 view.setId(mInflatedId);
269 }
270
271 final int index = parent.indexOfChild(this);
272 parent.removeViewInLayout(this);
273
274 final ViewGroup.LayoutParams layoutParams = getLayoutParams();
275 if (layoutParams != null) {
276 parent.addView(view, index, layoutParams);
277 } else {
278 parent.addView(view, index);
279 }
280
Adam Powell58acbaf2009-12-15 11:43:34 -0800281 mInflatedViewRef = new WeakReference<View>(view);
Mihai Predab6af5332009-04-28 14:21:57 +0200282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 if (mInflateListener != null) {
284 mInflateListener.onInflate(this, view);
285 }
286
287 return view;
288 } else {
289 throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
290 }
291 } else {
292 throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");
293 }
294 }
295
296 /**
297 * Specifies the inflate listener to be notified after this ViewStub successfully
298 * inflated its layout resource.
299 *
300 * @param inflateListener The OnInflateListener to notify of successful inflation.
301 *
302 * @see android.view.ViewStub.OnInflateListener
303 */
304 public void setOnInflateListener(OnInflateListener inflateListener) {
305 mInflateListener = inflateListener;
306 }
307
308 /**
309 * Listener used to receive a notification after a ViewStub has successfully
310 * inflated its layout resource.
311 *
312 * @see android.view.ViewStub#setOnInflateListener(android.view.ViewStub.OnInflateListener)
313 */
314 public static interface OnInflateListener {
315 /**
316 * Invoked after a ViewStub successfully inflated its layout resource.
317 * This method is invoked after the inflated view was added to the
318 * hierarchy but before the layout pass.
319 *
320 * @param stub The ViewStub that initiated the inflation.
321 * @param inflated The inflated View.
322 */
323 void onInflate(ViewStub stub, View inflated);
324 }
325}