blob: 0d8ec989ab2ac7a7f8359bd618c0d594c2162487 [file] [log] [blame]
Dianne Hackborn5ddd1272010-06-12 10:15:28 -07001/*
2 * Copyright (C) 2010 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.os.Bundle;
20import android.os.Handler;
21import android.view.LayoutInflater;
22import android.view.View;
23import android.view.ViewGroup;
24import android.widget.AdapterView;
25import android.widget.ListAdapter;
26import android.widget.ListView;
27
28/**
29 * An fragment that displays a list of items by binding to a data source such as
30 * an array or Cursor, and exposes event handlers when the user selects an item.
31 * <p>
32 * ListActivity hosts a {@link android.widget.ListView ListView} object that can
33 * be bound to different data sources, typically either an array or a Cursor
34 * holding query results. Binding, screen layout, and row layout are discussed
35 * in the following sections.
36 * <p>
37 * <strong>Screen Layout</strong>
38 * </p>
39 * <p>
40 * ListActivity has a default layout that consists of a single list view.
41 * However, if you desire, you can customize the fragment layout by returning
42 * your own view hierarchy from {@link #onCreateView}.
43 * To do this, your view hierarchy MUST contain a ListView object with the
44 * id "@android:id/list" (or {@link android.R.id#list} if it's in code)
45 * <p>
46 * Optionally, your view hierarchy can contain another view object of any type to
47 * display when the list view is empty. This "empty list" notifier must have an
48 * id "android:empty". Note that when an empty view is present, the list view
49 * will be hidden when there is no data to display.
50 * <p>
51 * The following code demonstrates an (ugly) custom lisy layout. It has a list
52 * with a green background, and an alternate red "no data" message.
53 * </p>
54 *
55 * <pre>
56 * &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
57 * &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
58 * android:orientation=&quot;vertical&quot;
59 * android:layout_width=&quot;match_parent&quot;
60 * android:layout_height=&quot;match_parent&quot;
61 * android:paddingLeft=&quot;8dp&quot;
62 * android:paddingRight=&quot;8dp&quot;&gt;
63 *
64 * &lt;ListView android:id=&quot;@id/android:list&quot;
65 * android:layout_width=&quot;match_parent&quot;
66 * android:layout_height=&quot;match_parent&quot;
67 * android:background=&quot;#00FF00&quot;
68 * android:layout_weight=&quot;1&quot;
69 * android:drawSelectorOnTop=&quot;false&quot;/&gt;
70 *
71 * &lt;TextView android:id=&quot;@id/android:empty&quot;
72 * android:layout_width=&quot;match_parent&quot;
73 * android:layout_height=&quot;match_parent&quot;
74 * android:background=&quot;#FF0000&quot;
75 * android:text=&quot;No data&quot;/&gt;
76 * &lt;/LinearLayout&gt;
77 * </pre>
78 *
79 * <p>
80 * <strong>Row Layout</strong>
81 * </p>
82 * <p>
83 * You can specify the layout of individual rows in the list. You do this by
84 * specifying a layout resource in the ListAdapter object hosted by the fragment
85 * (the ListAdapter binds the ListView to the data; more on this later).
86 * <p>
87 * A ListAdapter constructor takes a parameter that specifies a layout resource
88 * for each row. It also has two additional parameters that let you specify
89 * which data field to associate with which object in the row layout resource.
90 * These two parameters are typically parallel arrays.
91 * </p>
92 * <p>
93 * Android provides some standard row layout resources. These are in the
94 * {@link android.R.layout} class, and have names such as simple_list_item_1,
95 * simple_list_item_2, and two_line_list_item. The following layout XML is the
96 * source for the resource two_line_list_item, which displays two data
97 * fields,one above the other, for each list row.
98 * </p>
99 *
100 * <pre>
101 * &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
102 * &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
103 * android:layout_width=&quot;match_parent&quot;
104 * android:layout_height=&quot;wrap_content&quot;
105 * android:orientation=&quot;vertical&quot;&gt;
106 *
107 * &lt;TextView android:id=&quot;@+id/text1&quot;
108 * android:textSize=&quot;16sp&quot;
109 * android:textStyle=&quot;bold&quot;
110 * android:layout_width=&quot;match_parent&quot;
111 * android:layout_height=&quot;wrap_content&quot;/&gt;
112 *
113 * &lt;TextView android:id=&quot;@+id/text2&quot;
114 * android:textSize=&quot;16sp&quot;
115 * android:layout_width=&quot;match_parent&quot;
116 * android:layout_height=&quot;wrap_content&quot;/&gt;
117 * &lt;/LinearLayout&gt;
118 * </pre>
119 *
120 * <p>
121 * You must identify the data bound to each TextView object in this layout. The
122 * syntax for this is discussed in the next section.
123 * </p>
124 * <p>
125 * <strong>Binding to Data</strong>
126 * </p>
127 * <p>
128 * You bind the ListFragment's ListView object to data using a class that
129 * implements the {@link android.widget.ListAdapter ListAdapter} interface.
130 * Android provides two standard list adapters:
131 * {@link android.widget.SimpleAdapter SimpleAdapter} for static data (Maps),
132 * and {@link android.widget.SimpleCursorAdapter SimpleCursorAdapter} for Cursor
133 * query results.
134 * </p>
135 *
136 * @see #setListAdapter
137 * @see android.widget.ListView
138 */
139public class ListFragment extends Fragment {
140 final private Handler mHandler = new Handler();
141
142 final private Runnable mRequestFocus = new Runnable() {
143 public void run() {
144 mList.focusableViewAvailable(mList);
145 }
146 };
147
148 final private AdapterView.OnItemClickListener mOnClickListener
149 = new AdapterView.OnItemClickListener() {
150 public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
151 onListItemClick((ListView)parent, v, position, id);
152 }
153 };
154
155 ListAdapter mAdapter;
156 ListView mList;
157
158 public ListFragment() {
159 }
160
161 /**
162 * Provide default implementation to return a simple list view.
163 */
164 @Override
165 public View onCreateView(LayoutInflater inflater, ViewGroup container,
166 Bundle savedInstanceState) {
167 return inflater.inflate(com.android.internal.R.layout.list_content,
168 container, false);
169 }
170
171 /**
172 * Attach to list view once Fragment is ready to run.
173 */
174 @Override
175 public void onReady(Bundle savedInstanceState) {
176 super.onReady(savedInstanceState);
177 ensureList();
178 }
179
180 /**
181 * Detach from list view.
182 */
183 @Override
184 public void onDestroyView() {
185 mHandler.removeCallbacks(mRequestFocus);
186 mList = null;
187 super.onDestroyView();
188 }
189
190 /**
191 * This method will be called when an item in the list is selected.
192 * Subclasses should override. Subclasses can call
193 * getListView().getItemAtPosition(position) if they need to access the
194 * data associated with the selected item.
195 *
196 * @param l The ListView where the click happened
197 * @param v The view that was clicked within the ListView
198 * @param position The position of the view in the list
199 * @param id The row id of the item that was clicked
200 */
201 public void onListItemClick(ListView l, View v, int position, long id) {
202 }
203
204 /**
205 * Provide the cursor for the list view.
206 */
207 public void setListAdapter(ListAdapter adapter) {
208 mAdapter = adapter;
209 if (mList != null) {
210 mList.setAdapter(adapter);
211 }
212 }
213
214 /**
215 * Set the currently selected list item to the specified
216 * position with the adapter's data
217 *
218 * @param position
219 */
220 public void setSelection(int position) {
221 ensureList();
222 mList.setSelection(position);
223 }
224
225 /**
226 * Get the position of the currently selected list item.
227 */
228 public int getSelectedItemPosition() {
229 ensureList();
230 return mList.getSelectedItemPosition();
231 }
232
233 /**
234 * Get the cursor row ID of the currently selected list item.
235 */
236 public long getSelectedItemId() {
237 ensureList();
238 return mList.getSelectedItemId();
239 }
240
241 /**
242 * Get the activity's list view widget.
243 */
244 public ListView getListView() {
245 ensureList();
246 return mList;
247 }
248
249 /**
250 * Get the ListAdapter associated with this activity's ListView.
251 */
252 public ListAdapter getListAdapter() {
253 return mAdapter;
254 }
255
256 private void ensureList() {
257 if (mList != null) {
258 return;
259 }
260 View root = getView();
261 if (root == null) {
262 throw new IllegalStateException("Content view not yet created");
263 }
264 View emptyView = root.findViewById(com.android.internal.R.id.empty);
265 mList = (ListView)root.findViewById(com.android.internal.R.id.list);
266 if (mList == null) {
267 throw new RuntimeException(
268 "Your content must have a ListView whose id attribute is " +
269 "'android.R.id.list'");
270 }
271 if (emptyView != null) {
272 mList.setEmptyView(emptyView);
273 }
274 mList.setOnItemClickListener(mOnClickListener);
275 if (mAdapter != null) {
276 setListAdapter(mAdapter);
277 }
278 mHandler.post(mRequestFocus);
279 }
280}