Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package android.app; |
| 18 | |
| 19 | import android.os.Bundle; |
| 20 | import android.os.Handler; |
| 21 | import android.view.LayoutInflater; |
| 22 | import android.view.View; |
| 23 | import android.view.ViewGroup; |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 24 | import android.view.animation.AnimationUtils; |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 25 | import android.widget.AdapterView; |
| 26 | import android.widget.ListAdapter; |
| 27 | import android.widget.ListView; |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 28 | import android.widget.TextView; |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 29 | |
| 30 | /** |
Dianne Hackborn | dd913a5 | 2010-07-22 12:17:04 -0700 | [diff] [blame] | 31 | * A fragment that displays a list of items by binding to a data source such as |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 32 | * an array or Cursor, and exposes event handlers when the user selects an item. |
| 33 | * <p> |
Dianne Hackborn | dd913a5 | 2010-07-22 12:17:04 -0700 | [diff] [blame] | 34 | * ListFragment hosts a {@link android.widget.ListView ListView} object that can |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 35 | * be bound to different data sources, typically either an array or a Cursor |
| 36 | * holding query results. Binding, screen layout, and row layout are discussed |
| 37 | * in the following sections. |
| 38 | * <p> |
| 39 | * <strong>Screen Layout</strong> |
| 40 | * </p> |
| 41 | * <p> |
Dianne Hackborn | dd913a5 | 2010-07-22 12:17:04 -0700 | [diff] [blame] | 42 | * ListFragment has a default layout that consists of a single list view. |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 43 | * However, if you desire, you can customize the fragment layout by returning |
| 44 | * your own view hierarchy from {@link #onCreateView}. |
Dianne Hackborn | dd913a5 | 2010-07-22 12:17:04 -0700 | [diff] [blame] | 45 | * To do this, your view hierarchy <em>must</em> contain a ListView object with the |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 46 | * id "@android:id/list" (or {@link android.R.id#list} if it's in code) |
| 47 | * <p> |
| 48 | * Optionally, your view hierarchy can contain another view object of any type to |
| 49 | * display when the list view is empty. This "empty list" notifier must have an |
| 50 | * id "android:empty". Note that when an empty view is present, the list view |
| 51 | * will be hidden when there is no data to display. |
| 52 | * <p> |
Dianne Hackborn | dd913a5 | 2010-07-22 12:17:04 -0700 | [diff] [blame] | 53 | * The following code demonstrates an (ugly) custom list layout. It has a list |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 54 | * with a green background, and an alternate red "no data" message. |
| 55 | * </p> |
| 56 | * |
| 57 | * <pre> |
| 58 | * <?xml version="1.0" encoding="utf-8"?> |
| 59 | * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 60 | * android:orientation="vertical" |
| 61 | * android:layout_width="match_parent" |
| 62 | * android:layout_height="match_parent" |
| 63 | * android:paddingLeft="8dp" |
| 64 | * android:paddingRight="8dp"> |
| 65 | * |
| 66 | * <ListView android:id="@id/android:list" |
| 67 | * android:layout_width="match_parent" |
| 68 | * android:layout_height="match_parent" |
| 69 | * android:background="#00FF00" |
| 70 | * android:layout_weight="1" |
| 71 | * android:drawSelectorOnTop="false"/> |
| 72 | * |
| 73 | * <TextView android:id="@id/android:empty" |
| 74 | * android:layout_width="match_parent" |
| 75 | * android:layout_height="match_parent" |
| 76 | * android:background="#FF0000" |
| 77 | * android:text="No data"/> |
| 78 | * </LinearLayout> |
| 79 | * </pre> |
| 80 | * |
| 81 | * <p> |
| 82 | * <strong>Row Layout</strong> |
| 83 | * </p> |
| 84 | * <p> |
| 85 | * You can specify the layout of individual rows in the list. You do this by |
| 86 | * specifying a layout resource in the ListAdapter object hosted by the fragment |
| 87 | * (the ListAdapter binds the ListView to the data; more on this later). |
| 88 | * <p> |
| 89 | * A ListAdapter constructor takes a parameter that specifies a layout resource |
| 90 | * for each row. It also has two additional parameters that let you specify |
| 91 | * which data field to associate with which object in the row layout resource. |
| 92 | * These two parameters are typically parallel arrays. |
| 93 | * </p> |
| 94 | * <p> |
| 95 | * Android provides some standard row layout resources. These are in the |
| 96 | * {@link android.R.layout} class, and have names such as simple_list_item_1, |
| 97 | * simple_list_item_2, and two_line_list_item. The following layout XML is the |
| 98 | * source for the resource two_line_list_item, which displays two data |
| 99 | * fields,one above the other, for each list row. |
| 100 | * </p> |
| 101 | * |
| 102 | * <pre> |
| 103 | * <?xml version="1.0" encoding="utf-8"?> |
| 104 | * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 105 | * android:layout_width="match_parent" |
| 106 | * android:layout_height="wrap_content" |
| 107 | * android:orientation="vertical"> |
| 108 | * |
| 109 | * <TextView android:id="@+id/text1" |
| 110 | * android:textSize="16sp" |
| 111 | * android:textStyle="bold" |
| 112 | * android:layout_width="match_parent" |
| 113 | * android:layout_height="wrap_content"/> |
| 114 | * |
| 115 | * <TextView android:id="@+id/text2" |
| 116 | * android:textSize="16sp" |
| 117 | * android:layout_width="match_parent" |
| 118 | * android:layout_height="wrap_content"/> |
| 119 | * </LinearLayout> |
| 120 | * </pre> |
| 121 | * |
| 122 | * <p> |
| 123 | * You must identify the data bound to each TextView object in this layout. The |
| 124 | * syntax for this is discussed in the next section. |
| 125 | * </p> |
| 126 | * <p> |
| 127 | * <strong>Binding to Data</strong> |
| 128 | * </p> |
| 129 | * <p> |
| 130 | * You bind the ListFragment's ListView object to data using a class that |
| 131 | * implements the {@link android.widget.ListAdapter ListAdapter} interface. |
| 132 | * Android provides two standard list adapters: |
| 133 | * {@link android.widget.SimpleAdapter SimpleAdapter} for static data (Maps), |
| 134 | * and {@link android.widget.SimpleCursorAdapter SimpleCursorAdapter} for Cursor |
| 135 | * query results. |
| 136 | * </p> |
Dianne Hackborn | dd913a5 | 2010-07-22 12:17:04 -0700 | [diff] [blame] | 137 | * <p> |
| 138 | * You <b>must</b> use |
| 139 | * {@link #setListAdapter(ListAdapter) ListFragment.setListAdapter()} to |
| 140 | * associate the list with an adapter. Do not directly call |
| 141 | * {@link ListView#setAdapter(ListAdapter) ListView.setAdapter()} or else |
| 142 | * important initialization will be skipped. |
| 143 | * </p> |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 144 | * |
| 145 | * @see #setListAdapter |
| 146 | * @see android.widget.ListView |
Ian Lake | 0a1feb8 | 2017-11-13 10:26:46 -0800 | [diff] [blame] | 147 | * |
Ian Lake | 1f4e67b | 2017-12-18 10:36:18 -0800 | [diff] [blame] | 148 | * @deprecated Use the <a href="{@docRoot}tools/extras/support-library.html">Support Library</a> |
| 149 | * {@link android.support.v4.app.ListFragment} for consistent behavior across all devices |
| 150 | * and access to <a href="{@docRoot}topic/libraries/architecture/lifecycle.html">Lifecycle</a>. |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 151 | */ |
Ian Lake | 0a1feb8 | 2017-11-13 10:26:46 -0800 | [diff] [blame] | 152 | @Deprecated |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 153 | public class ListFragment extends Fragment { |
| 154 | final private Handler mHandler = new Handler(); |
| 155 | |
| 156 | final private Runnable mRequestFocus = new Runnable() { |
| 157 | public void run() { |
| 158 | mList.focusableViewAvailable(mList); |
| 159 | } |
| 160 | }; |
| 161 | |
| 162 | final private AdapterView.OnItemClickListener mOnClickListener |
| 163 | = new AdapterView.OnItemClickListener() { |
| 164 | public void onItemClick(AdapterView<?> parent, View v, int position, long id) { |
| 165 | onListItemClick((ListView)parent, v, position, id); |
| 166 | } |
| 167 | }; |
| 168 | |
| 169 | ListAdapter mAdapter; |
| 170 | ListView mList; |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 171 | View mEmptyView; |
| 172 | TextView mStandardEmptyView; |
| 173 | View mProgressContainer; |
| 174 | View mListContainer; |
Dianne Hackborn | afc4b28 | 2011-06-10 17:03:42 -0700 | [diff] [blame] | 175 | CharSequence mEmptyText; |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 176 | boolean mListShown; |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 177 | |
| 178 | public ListFragment() { |
| 179 | } |
| 180 | |
| 181 | /** |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 182 | * Provide default implementation to return a simple list view. Subclasses |
| 183 | * can override to replace with their own layout. If doing so, the |
| 184 | * returned view hierarchy <em>must</em> have a ListView whose id |
Dianne Hackborn | b0c56b2 | 2010-06-28 21:46:32 -0700 | [diff] [blame] | 185 | * is {@link android.R.id#list android.R.id.list} and can optionally |
| 186 | * have a sibling view id {@link android.R.id#empty android.R.id.empty} |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 187 | * that is to be shown when the list is empty. |
Dianne Hackborn | ef769f6 | 2010-07-12 11:40:53 -0700 | [diff] [blame] | 188 | * |
| 189 | * <p>If you are overriding this method with your own custom content, |
| 190 | * consider including the standard layout {@link android.R.layout#list_content} |
| 191 | * in your layout file, so that you continue to retain all of the standard |
| 192 | * behavior of ListFragment. In particular, this is currently the only |
| 193 | * way to have the built-in indeterminant progress state be shown. |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 194 | */ |
| 195 | @Override |
| 196 | public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| 197 | Bundle savedInstanceState) { |
Dianne Hackborn | ef769f6 | 2010-07-12 11:40:53 -0700 | [diff] [blame] | 198 | return inflater.inflate(com.android.internal.R.layout.list_content, |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 199 | container, false); |
| 200 | } |
| 201 | |
| 202 | /** |
Dianne Hackborn | 16f6e89 | 2011-04-15 19:00:20 -0700 | [diff] [blame] | 203 | * Attach to list view once the view hierarchy has been created. |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 204 | */ |
| 205 | @Override |
Dianne Hackborn | 16f6e89 | 2011-04-15 19:00:20 -0700 | [diff] [blame] | 206 | public void onViewCreated(View view, Bundle savedInstanceState) { |
| 207 | super.onViewCreated(view, savedInstanceState); |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 208 | ensureList(); |
| 209 | } |
| 210 | |
| 211 | /** |
| 212 | * Detach from list view. |
| 213 | */ |
| 214 | @Override |
| 215 | public void onDestroyView() { |
| 216 | mHandler.removeCallbacks(mRequestFocus); |
| 217 | mList = null; |
Dianne Hackborn | afc4b28 | 2011-06-10 17:03:42 -0700 | [diff] [blame] | 218 | mListShown = false; |
| 219 | mEmptyView = mProgressContainer = mListContainer = null; |
| 220 | mStandardEmptyView = null; |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 221 | super.onDestroyView(); |
| 222 | } |
| 223 | |
| 224 | /** |
| 225 | * This method will be called when an item in the list is selected. |
| 226 | * Subclasses should override. Subclasses can call |
| 227 | * getListView().getItemAtPosition(position) if they need to access the |
| 228 | * data associated with the selected item. |
| 229 | * |
| 230 | * @param l The ListView where the click happened |
| 231 | * @param v The view that was clicked within the ListView |
| 232 | * @param position The position of the view in the list |
| 233 | * @param id The row id of the item that was clicked |
| 234 | */ |
| 235 | public void onListItemClick(ListView l, View v, int position, long id) { |
| 236 | } |
| 237 | |
| 238 | /** |
| 239 | * Provide the cursor for the list view. |
| 240 | */ |
| 241 | public void setListAdapter(ListAdapter adapter) { |
Dianne Hackborn | ef769f6 | 2010-07-12 11:40:53 -0700 | [diff] [blame] | 242 | boolean hadAdapter = mAdapter != null; |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 243 | mAdapter = adapter; |
| 244 | if (mList != null) { |
| 245 | mList.setAdapter(adapter); |
Dianne Hackborn | ef769f6 | 2010-07-12 11:40:53 -0700 | [diff] [blame] | 246 | if (!mListShown && !hadAdapter) { |
| 247 | // The list was hidden, and previously didn't have an |
| 248 | // adapter. It is now time to show it. |
| 249 | setListShown(true, getView().getWindowToken() != null); |
| 250 | } |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 251 | } |
| 252 | } |
| 253 | |
| 254 | /** |
| 255 | * Set the currently selected list item to the specified |
| 256 | * position with the adapter's data |
| 257 | * |
| 258 | * @param position |
| 259 | */ |
| 260 | public void setSelection(int position) { |
| 261 | ensureList(); |
| 262 | mList.setSelection(position); |
| 263 | } |
| 264 | |
| 265 | /** |
| 266 | * Get the position of the currently selected list item. |
| 267 | */ |
| 268 | public int getSelectedItemPosition() { |
| 269 | ensureList(); |
| 270 | return mList.getSelectedItemPosition(); |
| 271 | } |
| 272 | |
| 273 | /** |
| 274 | * Get the cursor row ID of the currently selected list item. |
| 275 | */ |
| 276 | public long getSelectedItemId() { |
| 277 | ensureList(); |
| 278 | return mList.getSelectedItemId(); |
| 279 | } |
| 280 | |
| 281 | /** |
Adam Powell | 31479e3 | 2016-04-22 11:27:31 -0700 | [diff] [blame] | 282 | * Get the fragment's list view widget. |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 283 | */ |
| 284 | public ListView getListView() { |
| 285 | ensureList(); |
| 286 | return mList; |
| 287 | } |
| 288 | |
| 289 | /** |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 290 | * The default content for a ListFragment has a TextView that can |
| 291 | * be shown when the list is empty. If you would like to have it |
| 292 | * shown, call this method to supply the text it should use. |
| 293 | */ |
| 294 | public void setEmptyText(CharSequence text) { |
| 295 | ensureList(); |
| 296 | if (mStandardEmptyView == null) { |
| 297 | throw new IllegalStateException("Can't be used with a custom content view"); |
| 298 | } |
Dianne Hackborn | dd913a5 | 2010-07-22 12:17:04 -0700 | [diff] [blame] | 299 | mStandardEmptyView.setText(text); |
Dianne Hackborn | afc4b28 | 2011-06-10 17:03:42 -0700 | [diff] [blame] | 300 | if (mEmptyText == null) { |
Dianne Hackborn | dd913a5 | 2010-07-22 12:17:04 -0700 | [diff] [blame] | 301 | mList.setEmptyView(mStandardEmptyView); |
Dianne Hackborn | dd913a5 | 2010-07-22 12:17:04 -0700 | [diff] [blame] | 302 | } |
Dianne Hackborn | afc4b28 | 2011-06-10 17:03:42 -0700 | [diff] [blame] | 303 | mEmptyText = text; |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 304 | } |
| 305 | |
| 306 | /** |
| 307 | * Control whether the list is being displayed. You can make it not |
| 308 | * displayed if you are waiting for the initial data to show in it. During |
| 309 | * this time an indeterminant progress indicator will be shown instead. |
| 310 | * |
Dianne Hackborn | ef769f6 | 2010-07-12 11:40:53 -0700 | [diff] [blame] | 311 | * <p>Applications do not normally need to use this themselves. The default |
| 312 | * behavior of ListFragment is to start with the list not being shown, only |
| 313 | * showing it once an adapter is given with {@link #setListAdapter(ListAdapter)}. |
| 314 | * If the list at that point had not been shown, when it does get shown |
| 315 | * it will be do without the user ever seeing the hidden state. |
| 316 | * |
| 317 | * @param shown If true, the list view is shown; if false, the progress |
| 318 | * indicator. The initial value is true. |
| 319 | */ |
| 320 | public void setListShown(boolean shown) { |
| 321 | setListShown(shown, true); |
| 322 | } |
| 323 | |
| 324 | /** |
| 325 | * Like {@link #setListShown(boolean)}, but no animation is used when |
| 326 | * transitioning from the previous state. |
| 327 | */ |
| 328 | public void setListShownNoAnimation(boolean shown) { |
| 329 | setListShown(shown, false); |
| 330 | } |
| 331 | |
| 332 | /** |
| 333 | * Control whether the list is being displayed. You can make it not |
| 334 | * displayed if you are waiting for the initial data to show in it. During |
| 335 | * this time an indeterminant progress indicator will be shown instead. |
| 336 | * |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 337 | * @param shown If true, the list view is shown; if false, the progress |
| 338 | * indicator. The initial value is true. |
| 339 | * @param animate If true, an animation will be used to transition to the |
| 340 | * new state. |
| 341 | */ |
Dianne Hackborn | ef769f6 | 2010-07-12 11:40:53 -0700 | [diff] [blame] | 342 | private void setListShown(boolean shown, boolean animate) { |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 343 | ensureList(); |
| 344 | if (mProgressContainer == null) { |
| 345 | throw new IllegalStateException("Can't be used with a custom content view"); |
| 346 | } |
| 347 | if (mListShown == shown) { |
| 348 | return; |
| 349 | } |
| 350 | mListShown = shown; |
| 351 | if (shown) { |
| 352 | if (animate) { |
| 353 | mProgressContainer.startAnimation(AnimationUtils.loadAnimation( |
Adam Powell | 31479e3 | 2016-04-22 11:27:31 -0700 | [diff] [blame] | 354 | getContext(), android.R.anim.fade_out)); |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 355 | mListContainer.startAnimation(AnimationUtils.loadAnimation( |
Adam Powell | 31479e3 | 2016-04-22 11:27:31 -0700 | [diff] [blame] | 356 | getContext(), android.R.anim.fade_in)); |
Dianne Hackborn | afc4b28 | 2011-06-10 17:03:42 -0700 | [diff] [blame] | 357 | } else { |
| 358 | mProgressContainer.clearAnimation(); |
| 359 | mListContainer.clearAnimation(); |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 360 | } |
| 361 | mProgressContainer.setVisibility(View.GONE); |
| 362 | mListContainer.setVisibility(View.VISIBLE); |
| 363 | } else { |
| 364 | if (animate) { |
| 365 | mProgressContainer.startAnimation(AnimationUtils.loadAnimation( |
Adam Powell | 31479e3 | 2016-04-22 11:27:31 -0700 | [diff] [blame] | 366 | getContext(), android.R.anim.fade_in)); |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 367 | mListContainer.startAnimation(AnimationUtils.loadAnimation( |
Adam Powell | 31479e3 | 2016-04-22 11:27:31 -0700 | [diff] [blame] | 368 | getContext(), android.R.anim.fade_out)); |
Dianne Hackborn | afc4b28 | 2011-06-10 17:03:42 -0700 | [diff] [blame] | 369 | } else { |
| 370 | mProgressContainer.clearAnimation(); |
| 371 | mListContainer.clearAnimation(); |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 372 | } |
| 373 | mProgressContainer.setVisibility(View.VISIBLE); |
| 374 | mListContainer.setVisibility(View.GONE); |
| 375 | } |
| 376 | } |
| 377 | |
| 378 | /** |
Adam Powell | 31479e3 | 2016-04-22 11:27:31 -0700 | [diff] [blame] | 379 | * Get the ListAdapter associated with this fragment's ListView. |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 380 | */ |
| 381 | public ListAdapter getListAdapter() { |
| 382 | return mAdapter; |
| 383 | } |
| 384 | |
| 385 | private void ensureList() { |
| 386 | if (mList != null) { |
| 387 | return; |
| 388 | } |
| 389 | View root = getView(); |
| 390 | if (root == null) { |
| 391 | throw new IllegalStateException("Content view not yet created"); |
| 392 | } |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 393 | if (root instanceof ListView) { |
| 394 | mList = (ListView)root; |
| 395 | } else { |
| 396 | mStandardEmptyView = (TextView)root.findViewById( |
| 397 | com.android.internal.R.id.internalEmpty); |
| 398 | if (mStandardEmptyView == null) { |
| 399 | mEmptyView = root.findViewById(android.R.id.empty); |
Dianne Hackborn | afc4b28 | 2011-06-10 17:03:42 -0700 | [diff] [blame] | 400 | } else { |
| 401 | mStandardEmptyView.setVisibility(View.GONE); |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 402 | } |
| 403 | mProgressContainer = root.findViewById(com.android.internal.R.id.progressContainer); |
| 404 | mListContainer = root.findViewById(com.android.internal.R.id.listContainer); |
| 405 | View rawListView = root.findViewById(android.R.id.list); |
| 406 | if (!(rawListView instanceof ListView)) { |
| 407 | throw new RuntimeException( |
| 408 | "Content has view with id attribute 'android.R.id.list' " |
| 409 | + "that is not a ListView class"); |
| 410 | } |
| 411 | mList = (ListView)rawListView; |
| 412 | if (mList == null) { |
| 413 | throw new RuntimeException( |
| 414 | "Your content must have a ListView whose id attribute is " + |
| 415 | "'android.R.id.list'"); |
| 416 | } |
| 417 | if (mEmptyView != null) { |
| 418 | mList.setEmptyView(mEmptyView); |
Dianne Hackborn | afc4b28 | 2011-06-10 17:03:42 -0700 | [diff] [blame] | 419 | } else if (mEmptyText != null) { |
| 420 | mStandardEmptyView.setText(mEmptyText); |
| 421 | mList.setEmptyView(mStandardEmptyView); |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 422 | } |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 423 | } |
Dianne Hackborn | 445646c | 2010-06-25 15:52:59 -0700 | [diff] [blame] | 424 | mListShown = true; |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 425 | mList.setOnItemClickListener(mOnClickListener); |
| 426 | if (mAdapter != null) { |
Dianne Hackborn | afc4b28 | 2011-06-10 17:03:42 -0700 | [diff] [blame] | 427 | ListAdapter adapter = mAdapter; |
| 428 | mAdapter = null; |
| 429 | setListAdapter(adapter); |
Dianne Hackborn | ef769f6 | 2010-07-12 11:40:53 -0700 | [diff] [blame] | 430 | } else { |
| 431 | // We are starting without an adapter, so assume we won't |
| 432 | // have our data right away and start with the progress indicator. |
| 433 | if (mProgressContainer != null) { |
| 434 | setListShown(false, false); |
| 435 | } |
Dianne Hackborn | 5ddd127 | 2010-06-12 10:15:28 -0700 | [diff] [blame] | 436 | } |
| 437 | mHandler.post(mRequestFocus); |
| 438 | } |
| 439 | } |