OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / core / java / android / app / ExpandableListActivity.java
1 /*
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
17 package android.app;
18
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;
31
32 import java.util.Map;
33
34 /**
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.
38  * <p>
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.
44  * <p>
45  * <strong>Screen Layout</strong>
46  * </p>
47  * <p>
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)
54  * <p>
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.
59  * <p>
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.
62  * </p>
63  * 
64  * <pre>
65  * &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
66  * &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
67  *         android:orientation=&quot;vertical&quot;
68  *         android:layout_width=&quot;match_parent&quot; 
69  *         android:layout_height=&quot;match_parent&quot;
70  *         android:paddingLeft=&quot;8dp&quot;
71  *         android:paddingRight=&quot;8dp&quot;&gt;
72  * 
73  *     &lt;ExpandableListView android:id=&quot;@id/android:list&quot;
74  *               android:layout_width=&quot;match_parent&quot; 
75  *               android:layout_height=&quot;match_parent&quot;
76  *               android:background=&quot;#00FF00&quot;
77  *               android:layout_weight=&quot;1&quot;
78  *               android:drawSelectorOnTop=&quot;false&quot;/&gt;
79  * 
80  *     &lt;TextView android:id=&quot;@id/android:empty&quot;
81  *               android:layout_width=&quot;match_parent&quot; 
82  *               android:layout_height=&quot;match_parent&quot;
83  *               android:background=&quot;#FF0000&quot;
84  *               android:text=&quot;No data&quot;/&gt;
85  * &lt;/LinearLayout&gt;
86  * </pre>
87  * 
88  * <p>
89  * <strong>Row Layout</strong>
90  * </p>
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}.
97  * <p>
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.
105  * </p>
106  * <p>
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.
112  * </p>
113  * 
114  * <pre>
115  * &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
116  * &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
117  *     android:layout_width=&quot;match_parent&quot;
118  *     android:layout_height=&quot;wrap_content&quot;
119  *     android:orientation=&quot;vertical&quot;&gt;
120  * 
121  *     &lt;TextView android:id=&quot;@+id/text1&quot;
122  *         android:textSize=&quot;16sp&quot;
123  *         android:textStyle=&quot;bold&quot;
124  *         android:layout_width=&quot;match_parent&quot;
125  *         android:layout_height=&quot;wrap_content&quot;/&gt;
126  * 
127  *     &lt;TextView android:id=&quot;@+id/text2&quot;
128  *         android:textSize=&quot;16sp&quot;
129  *         android:layout_width=&quot;match_parent&quot;
130  *         android:layout_height=&quot;wrap_content&quot;/&gt;
131  * &lt;/LinearLayout&gt;
132  * </pre>
133  * 
134  * <p>
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.
137  * </p>
138  * <p>
139  * <strong>Binding to Data</strong>
140  * </p>
141  * <p>
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.
150  * </p>
151  * 
152  * @see #setListAdapter
153  * @see android.widget.ExpandableListView
154  */
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;
162
163     /**
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.
169      * <p>
170      * {@inheritDoc}
171      */
172     @Override
173     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
174     }
175
176     /**
177      * Override this for receiving callbacks when a child has been clicked.
178      * <p>
179      * {@inheritDoc}
180      */
181     public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
182             int childPosition, long id) {
183         return false;
184     }
185
186     /**
187      * Override this for receiving callbacks when a group has been collapsed.
188      */
189     public void onGroupCollapse(int groupPosition) {
190     }
191
192     /**
193      * Override this for receiving callbacks when a group has been expanded.
194      */
195     public void onGroupExpand(int groupPosition) {
196     }
197
198     /**
199      * Ensures the expandable list view has been created before Activity restores all
200      * of the view states.
201      * 
202      *@see Activity#onRestoreInstanceState(Bundle)
203      */
204     @Override
205     protected void onRestoreInstanceState(Bundle state) {
206         ensureList();
207         super.onRestoreInstanceState(state);
208     }
209
210     /**
211      * Updates the screen state (current list and other views) when the
212      * content changes.
213      * 
214      * @see Activity#onContentChanged()
215      */
216     @Override
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);
221         if (mList == null) {
222             throw new RuntimeException(
223                     "Your content must have a ExpandableListView whose id attribute is " +
224                     "'android.R.id.list'");
225         }
226         if (emptyView != null) {
227             mList.setEmptyView(emptyView);
228         }
229         mList.setOnChildClickListener(this);
230         mList.setOnGroupExpandListener(this);
231         mList.setOnGroupCollapseListener(this);
232         
233         if (mFinishedStart) {
234             setListAdapter(mAdapter);
235         }
236         mFinishedStart = true;
237     }
238
239     /**
240      * Provide the adapter for the expandable list.
241      */
242     public void setListAdapter(ExpandableListAdapter adapter) {
243         synchronized (this) {
244             ensureList();
245             mAdapter = adapter;
246             mList.setAdapter(adapter);
247         }
248     }
249
250     /**
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.
253      * 
254      * @see ExpandableListView
255      */
256     public ExpandableListView getExpandableListView() {
257         ensureList();
258         return mList;
259     }
260     
261     /**
262      * Get the ExpandableListAdapter associated with this activity's
263      * ExpandableListView.
264      */
265     public ExpandableListAdapter getExpandableListAdapter() {
266         return mAdapter;
267     }
268
269     private void ensureList() {
270         if (mList != null) {
271             return;
272         }
273         setContentView(com.android.internal.R.layout.expandable_list_content);
274     }
275
276     /**
277      * Gets the ID of the currently selected group or child.
278      * 
279      * @return The ID of the currently selected group or child.
280      */
281     public long getSelectedId() {
282         return mList.getSelectedId();
283     }
284
285     /**
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
291      * packed position.
292      * 
293      * @return A packed position representation containing the currently
294      *         selected group or child's position and type.
295      */
296     public long getSelectedPosition() {
297         return mList.getSelectedPosition();
298     }
299
300     /**
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.
304      * 
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
308      *            it is collapsed.
309      * @return Whether the selection was successfully set on the child.
310      */
311     public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) {
312         return mList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup);
313     }
314
315     /**
316      * Sets the selection to the specified group.
317      * @param groupPosition The position of the group that should be selected.
318      */
319     public void setSelectedGroup(int groupPosition) {
320         mList.setSelectedGroup(groupPosition);
321     }
322
323 }
324