Home | History | Annotate | Download | only in app
      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.os.Bundle;
     20 import android.os.Handler;
     21 import android.view.View;
     22 import android.widget.AdapterView;
     23 import android.widget.ListAdapter;
     24 import android.widget.ListView;
     25 
     26 /**
     27  * An activity that displays a list of items by binding to a data source such as
     28  * an array or Cursor, and exposes event handlers when the user selects an item.
     29  * <p>
     30  * ListActivity hosts a {@link android.widget.ListView ListView} object that can
     31  * be bound to different data sources, typically either an array or a Cursor
     32  * holding query results. Binding, screen layout, and row layout are discussed
     33  * in the following sections.
     34  * <p>
     35  * <strong>Screen Layout</strong>
     36  * </p>
     37  * <p>
     38  * ListActivity has a default layout that consists of a single, full-screen list
     39  * in the center of the screen. However, if you desire, you can customize the
     40  * screen layout by setting your own view layout with setContentView() in
     41  * onCreate(). To do this, your own view MUST contain a ListView object with the
     42  * id "@android:id/list" (or {@link android.R.id#list} if it's in code)
     43  * <p>
     44  * Optionally, your custom view can contain another view object of any type to
     45  * display when the list view is empty. This "empty list" notifier must have an
     46  * id "android:id/empty". Note that when an empty view is present, the list view
     47  * will be hidden when there is no data to display.
     48  * <p>
     49  * The following code demonstrates an (ugly) custom screen layout. It has a list
     50  * with a green background, and an alternate red "no data" message.
     51  * </p>
     52  *
     53  * <pre>
     54  * &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
     55  * &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     56  *         android:orientation=&quot;vertical&quot;
     57  *         android:layout_width=&quot;match_parent&quot;
     58  *         android:layout_height=&quot;match_parent&quot;
     59  *         android:paddingLeft=&quot;8dp&quot;
     60  *         android:paddingRight=&quot;8dp&quot;&gt;
     61  *
     62  *     &lt;ListView android:id=&quot;@android:id/list&quot;
     63  *               android:layout_width=&quot;match_parent&quot;
     64  *               android:layout_height=&quot;match_parent&quot;
     65  *               android:background=&quot;#00FF00&quot;
     66  *               android:layout_weight=&quot;1&quot;
     67  *               android:drawSelectorOnTop=&quot;false&quot;/&gt;
     68  *
     69  *     &lt;TextView android:id=&quot;@android:id/empty&quot;
     70  *               android:layout_width=&quot;match_parent&quot;
     71  *               android:layout_height=&quot;match_parent&quot;
     72  *               android:background=&quot;#FF0000&quot;
     73  *               android:text=&quot;No data&quot;/&gt;
     74  * &lt;/LinearLayout&gt;
     75  * </pre>
     76  *
     77  * <p>
     78  * <strong>Row Layout</strong>
     79  * </p>
     80  * <p>
     81  * You can specify the layout of individual rows in the list. You do this by
     82  * specifying a layout resource in the ListAdapter object hosted by the activity
     83  * (the ListAdapter binds the ListView to the data; more on this later).
     84  * <p>
     85  * A ListAdapter constructor takes a parameter that specifies a layout resource
     86  * for each row. It also has two additional parameters that let you specify
     87  * which data field to associate with which object in the row layout resource.
     88  * These two parameters are typically parallel arrays.
     89  * </p>
     90  * <p>
     91  * Android provides some standard row layout resources. These are in the
     92  * {@link android.R.layout} class, and have names such as simple_list_item_1,
     93  * simple_list_item_2, and two_line_list_item. The following layout XML is the
     94  * source for the resource two_line_list_item, which displays two data
     95  * fields,one above the other, for each list row.
     96  * </p>
     97  *
     98  * <pre>
     99  * &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
    100  * &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    101  *     android:layout_width=&quot;match_parent&quot;
    102  *     android:layout_height=&quot;wrap_content&quot;
    103  *     android:orientation=&quot;vertical&quot;&gt;
    104  *
    105  *     &lt;TextView android:id=&quot;@+id/text1&quot;
    106  *         android:textSize=&quot;16sp&quot;
    107  *         android:textStyle=&quot;bold&quot;
    108  *         android:layout_width=&quot;match_parent&quot;
    109  *         android:layout_height=&quot;wrap_content&quot;/&gt;
    110  *
    111  *     &lt;TextView android:id=&quot;@+id/text2&quot;
    112  *         android:textSize=&quot;16sp&quot;
    113  *         android:layout_width=&quot;match_parent&quot;
    114  *         android:layout_height=&quot;wrap_content&quot;/&gt;
    115  * &lt;/LinearLayout&gt;
    116  * </pre>
    117  *
    118  * <p>
    119  * You must identify the data bound to each TextView object in this layout. The
    120  * syntax for this is discussed in the next section.
    121  * </p>
    122  * <p>
    123  * <strong>Binding to Data</strong>
    124  * </p>
    125  * <p>
    126  * You bind the ListActivity's ListView object to data using a class that
    127  * implements the {@link android.widget.ListAdapter ListAdapter} interface.
    128  * Android provides two standard list adapters:
    129  * {@link android.widget.SimpleAdapter SimpleAdapter} for static data (Maps),
    130  * and {@link android.widget.SimpleCursorAdapter SimpleCursorAdapter} for Cursor
    131  * query results.
    132  * </p>
    133  * <p>
    134  * The following code from a custom ListActivity demonstrates querying the
    135  * Contacts provider for all contacts, then binding the Name and Company fields
    136  * to a two line row layout in the activity's ListView.
    137  * </p>
    138  *
    139  * <pre>
    140  * public class MyListAdapter extends ListActivity {
    141  *
    142  *     &#064;Override
    143  *     protected void onCreate(Bundle savedInstanceState){
    144  *         super.onCreate(savedInstanceState);
    145  *
    146  *         // We'll define a custom screen layout here (the one shown above), but
    147  *         // typically, you could just use the standard ListActivity layout.
    148  *         setContentView(R.layout.custom_list_activity_view);
    149  *
    150  *         // Query for all people contacts using the {@link android.provider.Contacts.People} convenience class.
    151  *         // Put a managed wrapper around the retrieved cursor so we don't have to worry about
    152  *         // requerying or closing it as the activity changes state.
    153  *         mCursor = this.getContentResolver().query(People.CONTENT_URI, null, null, null, null);
    154  *         startManagingCursor(mCursor);
    155  *
    156  *         // Now create a new list adapter bound to the cursor.
    157  *         // SimpleListAdapter is designed for binding to a Cursor.
    158  *         ListAdapter adapter = new SimpleCursorAdapter(
    159  *                 this, // Context.
    160  *                 android.R.layout.two_line_list_item,  // Specify the row template to use (here, two columns bound to the two retrieved cursor
    161  * rows).
    162  *                 mCursor,                                              // Pass in the cursor to bind to.
    163  *                 new String[] {People.NAME, People.COMPANY},           // Array of cursor columns to bind to.
    164  *                 new int[] {android.R.id.text1, android.R.id.text2});  // Parallel array of which template objects to bind to those columns.
    165  *
    166  *         // Bind to our new adapter.
    167  *         setListAdapter(adapter);
    168  *     }
    169  * }
    170  * </pre>
    171  *
    172  * @see #setListAdapter
    173  * @see android.widget.ListView
    174  */
    175 public class ListActivity extends Activity {
    176     /**
    177      * This field should be made private, so it is hidden from the SDK.
    178      * {@hide}
    179      */
    180     protected ListAdapter mAdapter;
    181     /**
    182      * This field should be made private, so it is hidden from the SDK.
    183      * {@hide}
    184      */
    185     protected ListView mList;
    186 
    187     private Handler mHandler = new Handler();
    188     private boolean mFinishedStart = false;
    189 
    190     private Runnable mRequestFocus = new Runnable() {
    191         public void run() {
    192             mList.focusableViewAvailable(mList);
    193         }
    194     };
    195 
    196     /**
    197      * This method will be called when an item in the list is selected.
    198      * Subclasses should override. Subclasses can call
    199      * getListView().getItemAtPosition(position) if they need to access the
    200      * data associated with the selected item.
    201      *
    202      * @param l The ListView where the click happened
    203      * @param v The view that was clicked within the ListView
    204      * @param position The position of the view in the list
    205      * @param id The row id of the item that was clicked
    206      */
    207     protected void onListItemClick(ListView l, View v, int position, long id) {
    208     }
    209 
    210     /**
    211      * Ensures the list view has been created before Activity restores all
    212      * of the view states.
    213      *
    214      *@see Activity#onRestoreInstanceState(Bundle)
    215      */
    216     @Override
    217     protected void onRestoreInstanceState(Bundle state) {
    218         ensureList();
    219         super.onRestoreInstanceState(state);
    220     }
    221 
    222     /**
    223      * @see Activity#onDestroy()
    224      */
    225     @Override
    226     protected void onDestroy() {
    227         mHandler.removeCallbacks(mRequestFocus);
    228         super.onDestroy();
    229     }
    230 
    231     /**
    232      * Updates the screen state (current list and other views) when the
    233      * content changes.
    234      *
    235      * @see Activity#onContentChanged()
    236      */
    237     @Override
    238     public void onContentChanged() {
    239         super.onContentChanged();
    240         View emptyView = findViewById(com.android.internal.R.id.empty);
    241         mList = (ListView)findViewById(com.android.internal.R.id.list);
    242         if (mList == null) {
    243             throw new RuntimeException(
    244                     "Your content must have a ListView whose id attribute is " +
    245                     "'android.R.id.list'");
    246         }
    247         if (emptyView != null) {
    248             mList.setEmptyView(emptyView);
    249         }
    250         mList.setOnItemClickListener(mOnClickListener);
    251         if (mFinishedStart) {
    252             setListAdapter(mAdapter);
    253         }
    254         mHandler.post(mRequestFocus);
    255         mFinishedStart = true;
    256     }
    257 
    258     /**
    259      * Provide the cursor for the list view.
    260      */
    261     public void setListAdapter(ListAdapter adapter) {
    262         synchronized (this) {
    263             ensureList();
    264             mAdapter = adapter;
    265             mList.setAdapter(adapter);
    266         }
    267     }
    268 
    269     /**
    270      * Set the currently selected list item to the specified
    271      * position with the adapter's data
    272      *
    273      * @param position
    274      */
    275     public void setSelection(int position) {
    276         mList.setSelection(position);
    277     }
    278 
    279     /**
    280      * Get the position of the currently selected list item.
    281      */
    282     public int getSelectedItemPosition() {
    283         return mList.getSelectedItemPosition();
    284     }
    285 
    286     /**
    287      * Get the cursor row ID of the currently selected list item.
    288      */
    289     public long getSelectedItemId() {
    290         return mList.getSelectedItemId();
    291     }
    292 
    293     /**
    294      * Get the activity's list view widget.
    295      */
    296     public ListView getListView() {
    297         ensureList();
    298         return mList;
    299     }
    300 
    301     /**
    302      * Get the ListAdapter associated with this activity's ListView.
    303      */
    304     public ListAdapter getListAdapter() {
    305         return mAdapter;
    306     }
    307 
    308     private void ensureList() {
    309         if (mList != null) {
    310             return;
    311         }
    312         setContentView(com.android.internal.R.layout.list_content_simple);
    313 
    314     }
    315 
    316     private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() {
    317         public void onItemClick(AdapterView<?> parent, View v, int position, long id)
    318         {
    319             onListItemClick((ListView)parent, v, position, id);
    320         }
    321     };
    322 }
    323