blob: e08f25a1c40c37d6f77171d4b6701104f31e09da [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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.app;
18
19import android.database.Cursor;
20import android.os.Bundle;
21import java.util.List;
22import android.view.ContextMenu;
23import android.view.View;
24import android.view.ContextMenu.ContextMenuInfo;
25import android.view.View.OnCreateContextMenuListener;
26import android.widget.ExpandableListAdapter;
27import android.widget.ExpandableListView;
28import android.widget.SimpleCursorTreeAdapter;
29import android.widget.SimpleExpandableListAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
31import java.util.Map;
32
33/**
34 * An activity that displays an expandable list of items by binding to a data
35 * source implementing the ExpandableListAdapter, and exposes event handlers
36 * when the user selects an item.
37 * <p>
38 * ExpandableListActivity hosts a
39 * {@link android.widget.ExpandableListView ExpandableListView} object that can
40 * be bound to different data sources that provide a two-levels of data (the
41 * top-level is group, and below each group are children). Binding, screen
42 * layout, and row layout are discussed in the following sections.
43 * <p>
44 * <strong>Screen Layout</strong>
45 * </p>
46 * <p>
47 * ExpandableListActivity has a default layout that consists of a single,
48 * full-screen, centered expandable list. However, if you desire, you can
49 * customize the screen layout by setting your own view layout with
50 * setContentView() in onCreate(). To do this, your own view MUST contain an
51 * ExpandableListView object with the id "@android:id/list" (or
52 * {@link android.R.id#list} if it's in code)
53 * <p>
54 * Optionally, your custom view can contain another view object of any type to
55 * display when the list view is empty. This "empty list" notifier must have an
56 * id "android:empty". Note that when an empty view is present, the expandable
57 * list view will be hidden when there is no data to display.
58 * <p>
59 * The following code demonstrates an (ugly) custom screen layout. It has a list
60 * with a green background, and an alternate red "no data" message.
61 * </p>
62 *
63 * <pre>
64 * &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
65 * &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
66 * android:orientation=&quot;vertical&quot;
Romain Guy980a9382010-01-08 15:06:28 -080067 * android:layout_width=&quot;match_parent&quot;
68 * android:layout_height=&quot;match_parent&quot;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 * android:paddingLeft=&quot;8dp&quot;
70 * android:paddingRight=&quot;8dp&quot;&gt;
71 *
72 * &lt;ExpandableListView android:id=&quot;@id/android:list&quot;
Romain Guy980a9382010-01-08 15:06:28 -080073 * android:layout_width=&quot;match_parent&quot;
74 * android:layout_height=&quot;match_parent&quot;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 * android:background=&quot;#00FF00&quot;
76 * android:layout_weight=&quot;1&quot;
77 * android:drawSelectorOnTop=&quot;false&quot;/&gt;
78 *
79 * &lt;TextView android:id=&quot;@id/android:empty&quot;
Romain Guy980a9382010-01-08 15:06:28 -080080 * android:layout_width=&quot;match_parent&quot;
81 * android:layout_height=&quot;match_parent&quot;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 * android:background=&quot;#FF0000&quot;
83 * android:text=&quot;No data&quot;/&gt;
84 * &lt;/LinearLayout&gt;
85 * </pre>
86 *
87 * <p>
88 * <strong>Row Layout</strong>
89 * </p>
90 * The {@link ExpandableListAdapter} set in the {@link ExpandableListActivity}
91 * via {@link #setListAdapter(ExpandableListAdapter)} provides the {@link View}s
92 * for each row. This adapter has separate methods for providing the group
93 * {@link View}s and child {@link View}s. There are a couple provided
94 * {@link ExpandableListAdapter}s that simplify use of adapters:
95 * {@link SimpleCursorTreeAdapter} and {@link SimpleExpandableListAdapter}.
96 * <p>
97 * With these, you can specify the layout of individual rows for groups and
98 * children in the list. These constructor takes a few parameters that specify
99 * layout resources for groups and children. It also has additional parameters
100 * that let you specify which data field to associate with which object in the
101 * row layout resource. The {@link SimpleCursorTreeAdapter} fetches data from
102 * {@link Cursor}s and the {@link SimpleExpandableListAdapter} fetches data
103 * from {@link List}s of {@link Map}s.
104 * </p>
105 * <p>
106 * Android provides some standard row layout resources. These are in the
107 * {@link android.R.layout} class, and have names such as simple_list_item_1,
108 * simple_list_item_2, and two_line_list_item. The following layout XML is the
109 * source for the resource two_line_list_item, which displays two data
110 * fields,one above the other, for each list row.
111 * </p>
112 *
113 * <pre>
114 * &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
115 * &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
Romain Guy980a9382010-01-08 15:06:28 -0800116 * android:layout_width=&quot;match_parent&quot;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 * android:layout_height=&quot;wrap_content&quot;
118 * android:orientation=&quot;vertical&quot;&gt;
119 *
120 * &lt;TextView android:id=&quot;@+id/text1&quot;
121 * android:textSize=&quot;16sp&quot;
122 * android:textStyle=&quot;bold&quot;
Romain Guy980a9382010-01-08 15:06:28 -0800123 * android:layout_width=&quot;match_parent&quot;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 * android:layout_height=&quot;wrap_content&quot;/&gt;
125 *
126 * &lt;TextView android:id=&quot;@+id/text2&quot;
127 * android:textSize=&quot;16sp&quot;
Romain Guy980a9382010-01-08 15:06:28 -0800128 * android:layout_width=&quot;match_parent&quot;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 * android:layout_height=&quot;wrap_content&quot;/&gt;
130 * &lt;/LinearLayout&gt;
131 * </pre>
132 *
133 * <p>
134 * You must identify the data bound to each TextView object in this layout. The
135 * syntax for this is discussed in the next section.
136 * </p>
137 * <p>
138 * <strong>Binding to Data</strong>
139 * </p>
140 * <p>
141 * You bind the ExpandableListActivity's ExpandableListView object to data using
142 * a class that implements the
143 * {@link android.widget.ExpandableListAdapter ExpandableListAdapter} interface.
144 * Android provides two standard list adapters:
145 * {@link android.widget.SimpleExpandableListAdapter SimpleExpandableListAdapter}
146 * for static data (Maps), and
147 * {@link android.widget.SimpleCursorTreeAdapter SimpleCursorTreeAdapter} for
148 * Cursor query results.
149 * </p>
150 *
151 * @see #setListAdapter
152 * @see android.widget.ExpandableListView
153 */
154public class ExpandableListActivity extends Activity implements
155 OnCreateContextMenuListener,
156 ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener,
157 ExpandableListView.OnGroupExpandListener {
158 ExpandableListAdapter mAdapter;
159 ExpandableListView mList;
160 boolean mFinishedStart = false;
161
162 /**
163 * Override this to populate the context menu when an item is long pressed. menuInfo
164 * will contain an {@link android.widget.ExpandableListView.ExpandableListContextMenuInfo}
165 * whose packedPosition is a packed position
166 * that should be used with {@link ExpandableListView#getPackedPositionType(long)} and
167 * the other similar methods.
168 * <p>
169 * {@inheritDoc}
170 */
171 @Override
172 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
173 }
174
175 /**
176 * Override this for receiving callbacks when a child has been clicked.
177 * <p>
178 * {@inheritDoc}
179 */
180 public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
181 int childPosition, long id) {
182 return false;
183 }
184
185 /**
186 * Override this for receiving callbacks when a group has been collapsed.
187 */
188 public void onGroupCollapse(int groupPosition) {
189 }
190
191 /**
192 * Override this for receiving callbacks when a group has been expanded.
193 */
194 public void onGroupExpand(int groupPosition) {
195 }
196
197 /**
198 * Ensures the expandable list view has been created before Activity restores all
199 * of the view states.
200 *
201 *@see Activity#onRestoreInstanceState(Bundle)
202 */
203 @Override
204 protected void onRestoreInstanceState(Bundle state) {
205 ensureList();
206 super.onRestoreInstanceState(state);
207 }
208
209 /**
210 * Updates the screen state (current list and other views) when the
211 * content changes.
212 *
213 * @see Activity#onContentChanged()
214 */
215 @Override
216 public void onContentChanged() {
217 super.onContentChanged();
218 View emptyView = findViewById(com.android.internal.R.id.empty);
219 mList = (ExpandableListView)findViewById(com.android.internal.R.id.list);
220 if (mList == null) {
221 throw new RuntimeException(
222 "Your content must have a ExpandableListView whose id attribute is " +
223 "'android.R.id.list'");
224 }
225 if (emptyView != null) {
226 mList.setEmptyView(emptyView);
227 }
228 mList.setOnChildClickListener(this);
229 mList.setOnGroupExpandListener(this);
230 mList.setOnGroupCollapseListener(this);
231
232 if (mFinishedStart) {
233 setListAdapter(mAdapter);
234 }
235 mFinishedStart = true;
236 }
237
238 /**
239 * Provide the adapter for the expandable list.
240 */
241 public void setListAdapter(ExpandableListAdapter adapter) {
242 synchronized (this) {
243 ensureList();
244 mAdapter = adapter;
245 mList.setAdapter(adapter);
246 }
247 }
248
249 /**
250 * Get the activity's expandable list view widget. This can be used to get the selection,
251 * set the selection, and many other useful functions.
252 *
253 * @see ExpandableListView
254 */
255 public ExpandableListView getExpandableListView() {
256 ensureList();
257 return mList;
258 }
259
260 /**
261 * Get the ExpandableListAdapter associated with this activity's
262 * ExpandableListView.
263 */
264 public ExpandableListAdapter getExpandableListAdapter() {
265 return mAdapter;
266 }
267
268 private void ensureList() {
269 if (mList != null) {
270 return;
271 }
272 setContentView(com.android.internal.R.layout.expandable_list_content);
273 }
274
275 /**
276 * Gets the ID of the currently selected group or child.
277 *
278 * @return The ID of the currently selected group or child.
279 */
280 public long getSelectedId() {
281 return mList.getSelectedId();
282 }
283
284 /**
285 * Gets the position (in packed position representation) of the currently
286 * selected group or child. Use
287 * {@link ExpandableListView#getPackedPositionType},
288 * {@link ExpandableListView#getPackedPositionGroup}, and
289 * {@link ExpandableListView#getPackedPositionChild} to unpack the returned
290 * packed position.
291 *
292 * @return A packed position representation containing the currently
293 * selected group or child's position and type.
294 */
295 public long getSelectedPosition() {
296 return mList.getSelectedPosition();
297 }
298
299 /**
300 * Sets the selection to the specified child. If the child is in a collapsed
301 * group, the group will only be expanded and child subsequently selected if
302 * shouldExpandGroup is set to true, otherwise the method will return false.
303 *
304 * @param groupPosition The position of the group that contains the child.
305 * @param childPosition The position of the child within the group.
306 * @param shouldExpandGroup Whether the child's group should be expanded if
307 * it is collapsed.
308 * @return Whether the selection was successfully set on the child.
309 */
310 public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) {
311 return mList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup);
312 }
313
314 /**
315 * Sets the selection to the specified group.
316 * @param groupPosition The position of the group that should be selected.
317 */
318 public void setSelectedGroup(int groupPosition) {
319 mList.setSelectedGroup(groupPosition);
320 }
321
322}
323