2 * Copyright (C) 2006 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 import android.database.Cursor;
20 import android.os.Bundle;
21 import java.util.List;
22 import android.view.ContextMenu;
23 import android.view.View;
24 import android.view.ContextMenu.ContextMenuInfo;
25 import android.view.View.OnCreateContextMenuListener;
26 import android.widget.ExpandableListAdapter;
27 import android.widget.ExpandableListView;
28 import android.widget.SimpleCursorTreeAdapter;
29 import android.widget.SimpleExpandableListAdapter;
30 import android.widget.AdapterView.AdapterContextMenuInfo;
35 * An activity that displays an expandable list of items by binding to a data
36 * source implementing the ExpandableListAdapter, and exposes event handlers
37 * when the user selects an item.
39 * ExpandableListActivity hosts a
40 * {@link android.widget.ExpandableListView ExpandableListView} object that can
41 * be bound to different data sources that provide a two-levels of data (the
42 * top-level is group, and below each group are children). Binding, screen
43 * layout, and row layout are discussed in the following sections.
45 * <strong>Screen Layout</strong>
48 * ExpandableListActivity has a default layout that consists of a single,
49 * full-screen, centered expandable list. However, if you desire, you can
50 * customize the screen layout by setting your own view layout with
51 * setContentView() in onCreate(). To do this, your own view MUST contain an
52 * ExpandableListView object with the id "@android:id/list" (or
53 * {@link android.R.id#list} if it's in code)
55 * Optionally, your custom view can contain another view object of any type to
56 * display when the list view is empty. This "empty list" notifier must have an
57 * id "android:empty". Note that when an empty view is present, the expandable
58 * list view will be hidden when there is no data to display.
60 * The following code demonstrates an (ugly) custom screen layout. It has a list
61 * with a green background, and an alternate red "no data" message.
65 * <?xml version="1.0" encoding="UTF-8"?>
66 * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
67 * android:orientation="vertical"
68 * android:layout_width="match_parent"
69 * android:layout_height="match_parent"
70 * android:paddingLeft="8dp"
71 * android:paddingRight="8dp">
73 * <ExpandableListView android:id="@id/android:list"
74 * android:layout_width="match_parent"
75 * android:layout_height="match_parent"
76 * android:background="#00FF00"
77 * android:layout_weight="1"
78 * android:drawSelectorOnTop="false"/>
80 * <TextView android:id="@id/android:empty"
81 * android:layout_width="match_parent"
82 * android:layout_height="match_parent"
83 * android:background="#FF0000"
84 * android:text="No data"/>
85 * </LinearLayout>
89 * <strong>Row Layout</strong>
91 * The {@link ExpandableListAdapter} set in the {@link ExpandableListActivity}
92 * via {@link #setListAdapter(ExpandableListAdapter)} provides the {@link View}s
93 * for each row. This adapter has separate methods for providing the group
94 * {@link View}s and child {@link View}s. There are a couple provided
95 * {@link ExpandableListAdapter}s that simplify use of adapters:
96 * {@link SimpleCursorTreeAdapter} and {@link SimpleExpandableListAdapter}.
98 * With these, you can specify the layout of individual rows for groups and
99 * children in the list. These constructor takes a few parameters that specify
100 * layout resources for groups and children. It also has additional parameters
101 * that let you specify which data field to associate with which object in the
102 * row layout resource. The {@link SimpleCursorTreeAdapter} fetches data from
103 * {@link Cursor}s and the {@link SimpleExpandableListAdapter} fetches data
104 * from {@link List}s of {@link Map}s.
107 * Android provides some standard row layout resources. These are in the
108 * {@link android.R.layout} class, and have names such as simple_list_item_1,
109 * simple_list_item_2, and two_line_list_item. The following layout XML is the
110 * source for the resource two_line_list_item, which displays two data
111 * fields,one above the other, for each list row.
115 * <?xml version="1.0" encoding="utf-8"?>
116 * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
117 * android:layout_width="match_parent"
118 * android:layout_height="wrap_content"
119 * android:orientation="vertical">
121 * <TextView android:id="@+id/text1"
122 * android:textSize="16sp"
123 * android:textStyle="bold"
124 * android:layout_width="match_parent"
125 * android:layout_height="wrap_content"/>
127 * <TextView android:id="@+id/text2"
128 * android:textSize="16sp"
129 * android:layout_width="match_parent"
130 * android:layout_height="wrap_content"/>
131 * </LinearLayout>
135 * You must identify the data bound to each TextView object in this layout. The
136 * syntax for this is discussed in the next section.
139 * <strong>Binding to Data</strong>
142 * You bind the ExpandableListActivity's ExpandableListView object to data using
143 * a class that implements the
144 * {@link android.widget.ExpandableListAdapter ExpandableListAdapter} interface.
145 * Android provides two standard list adapters:
146 * {@link android.widget.SimpleExpandableListAdapter SimpleExpandableListAdapter}
147 * for static data (Maps), and
148 * {@link android.widget.SimpleCursorTreeAdapter SimpleCursorTreeAdapter} for
149 * Cursor query results.
152 * @see #setListAdapter
153 * @see android.widget.ExpandableListView
155 public class ExpandableListActivity extends Activity implements
156 OnCreateContextMenuListener,
157 ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener,
158 ExpandableListView.OnGroupExpandListener {
159 ExpandableListAdapter mAdapter;
160 ExpandableListView mList;
161 boolean mFinishedStart = false;
164 * Override this to populate the context menu when an item is long pressed. menuInfo
165 * will contain an {@link android.widget.ExpandableListView.ExpandableListContextMenuInfo}
166 * whose packedPosition is a packed position
167 * that should be used with {@link ExpandableListView#getPackedPositionType(long)} and
168 * the other similar methods.
173 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
177 * Override this for receiving callbacks when a child has been clicked.
181 public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
182 int childPosition, long id) {
187 * Override this for receiving callbacks when a group has been collapsed.
189 public void onGroupCollapse(int groupPosition) {
193 * Override this for receiving callbacks when a group has been expanded.
195 public void onGroupExpand(int groupPosition) {
199 * Ensures the expandable list view has been created before Activity restores all
200 * of the view states.
202 *@see Activity#onRestoreInstanceState(Bundle)
205 protected void onRestoreInstanceState(Bundle state) {
207 super.onRestoreInstanceState(state);
211 * Updates the screen state (current list and other views) when the
214 * @see Activity#onContentChanged()
217 public void onContentChanged() {
218 super.onContentChanged();
219 View emptyView = findViewById(com.android.internal.R.id.empty);
220 mList = (ExpandableListView)findViewById(com.android.internal.R.id.list);
222 throw new RuntimeException(
223 "Your content must have a ExpandableListView whose id attribute is " +
224 "'android.R.id.list'");
226 if (emptyView != null) {
227 mList.setEmptyView(emptyView);
229 mList.setOnChildClickListener(this);
230 mList.setOnGroupExpandListener(this);
231 mList.setOnGroupCollapseListener(this);
233 if (mFinishedStart) {
234 setListAdapter(mAdapter);
236 mFinishedStart = true;
240 * Provide the adapter for the expandable list.
242 public void setListAdapter(ExpandableListAdapter adapter) {
243 synchronized (this) {
246 mList.setAdapter(adapter);
251 * Get the activity's expandable list view widget. This can be used to get the selection,
252 * set the selection, and many other useful functions.
254 * @see ExpandableListView
256 public ExpandableListView getExpandableListView() {
262 * Get the ExpandableListAdapter associated with this activity's
263 * ExpandableListView.
265 public ExpandableListAdapter getExpandableListAdapter() {
269 private void ensureList() {
273 setContentView(com.android.internal.R.layout.expandable_list_content);
277 * Gets the ID of the currently selected group or child.
279 * @return The ID of the currently selected group or child.
281 public long getSelectedId() {
282 return mList.getSelectedId();
286 * Gets the position (in packed position representation) of the currently
287 * selected group or child. Use
288 * {@link ExpandableListView#getPackedPositionType},
289 * {@link ExpandableListView#getPackedPositionGroup}, and
290 * {@link ExpandableListView#getPackedPositionChild} to unpack the returned
293 * @return A packed position representation containing the currently
294 * selected group or child's position and type.
296 public long getSelectedPosition() {
297 return mList.getSelectedPosition();
301 * Sets the selection to the specified child. If the child is in a collapsed
302 * group, the group will only be expanded and child subsequently selected if
303 * shouldExpandGroup is set to true, otherwise the method will return false.
305 * @param groupPosition The position of the group that contains the child.
306 * @param childPosition The position of the child within the group.
307 * @param shouldExpandGroup Whether the child's group should be expanded if
309 * @return Whether the selection was successfully set on the child.
311 public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) {
312 return mList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup);
316 * Sets the selection to the specified group.
317 * @param groupPosition The position of the group that should be selected.
319 public void setSelectedGroup(int groupPosition) {
320 mList.setSelectedGroup(groupPosition);