summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/topics/ui/layout/listview.jd
blob: 3c6e32ca41cfe002920e09d2c24dbeda72389545 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
page.title=List View
page.tags=listview
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
  <ol>
    <li><a href="#Loader">Using a Loader</a></li>
    <li><a href="#Example">Example</a></li>
  </ol>
  <h2>Key classes</h2>
  <ol>
    <li>{@link android.widget.ListView}</li>
    <li>{@link android.widget.Adapter}</li>
    <li>{@link android.support.v4.content.CursorLoader}</li>
  </ol>
  <h2>See also</h2>
  <ol>
    <li><a
href="{@docRoot}guide/components/loaders.html">Loaders</a></li>
  </ol>
</div>
</div>

<p>{@link android.widget.ListView} is a view group that displays a list of
scrollable items. The list items are automatically inserted to the list using an {@link
android.widget.Adapter} that pulls content from a source such as an array or database query and
converts each item result into a view that's placed into the list.</p>

<p>For an introduction to how you can dynamically insert views using an adapter, read
<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Building Layouts with
  an Adapter</a>.</p>

<img src="{@docRoot}images/ui/listview.png" alt="" />

<h2 id="Loader">Using a Loader</h2>

<p>Using a {@link
android.support.v4.content.CursorLoader} is the standard way to query a {@link
android.database.Cursor} as an asynchronous task in order to avoid blocking your app's main thread
with the query. When the {@link android.support.v4.content.CursorLoader} receives the {@link
android.database.Cursor} result, the {@link android.support.v4.app.LoaderManager.LoaderCallbacks
LoaderCallbacks} receives a callback to {@link
android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}, which is
where you update your {@link
android.widget.Adapter} with the new {@link android.database.Cursor} and the list view then
displays the results.</p>

<p>Although the {@link android.support.v4.content.CursorLoader} APIs were first introduced in
Android 3.0 (API level 11), they are also available in the <a
href="{@docRoot}tools/support-library/index.html">Support Library</a> so that your app may use them
while supporting devices running Android 1.6 or higher.</p>

<p>For more information about using a {@link
android.support.v4.content.Loader} to asynchronously load data, see the <a
href="{@docRoot}guide/components/loaders.html">Loaders</a> guide.</p>


<h2 id="Example">Example</h2>

<p>The following example uses {@link android.app.ListActivity}, which is an activity that includes
a {@link android.widget.ListView} as its only layout element by default. It performs a query to
the <a
href="{@docRoot}guide/topics/providers/contacts-provider.html">Contacts
Provider</a> for a list of names and phone numbers.</p>

<p>The activity implements the {@link android.support.v4.app.LoaderManager.LoaderCallbacks
LoaderCallbacks} interface in order to use a {@link android.support.v4.content.CursorLoader} that
dynamically loads the data for the list view.</p>

<pre>
public class ListViewLoader extends ListActivity
        implements LoaderManager.LoaderCallbacks&lt;Cursor> {

    // This is the Adapter being used to display the list's data
    SimpleCursorAdapter mAdapter;

    // These are the Contacts rows that we will retrieve
    static final String[] PROJECTION = new String[] {ContactsContract.Data._ID,
            ContactsContract.Data.DISPLAY_NAME};

    // This is the select criteria
    static final String SELECTION = "((" + 
            ContactsContract.Data.DISPLAY_NAME + " NOTNULL) AND (" +
            ContactsContract.Data.DISPLAY_NAME + " != '' ))";

    &#64;Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create a progress bar to display while the list loads
        ProgressBar progressBar = new ProgressBar(this);
        progressBar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT, Gravity.CENTER));
        progressBar.setIndeterminate(true);
        getListView().setEmptyView(progressBar);

        // Must add the progress bar to the root of the layout
        ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
        root.addView(progressBar);

        // For the cursor adapter, specify which columns go into which views
        String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};
        int[] toViews = {android.R.id.text1}; // The TextView in simple_list_item_1

        // Create an empty adapter we will use to display the loaded data.
        // We pass null for the cursor, then update it in onLoadFinished()
        mAdapter = new SimpleCursorAdapter(this, 
                android.R.layout.simple_list_item_1, null,
                fromColumns, toViews, 0);
        setListAdapter(mAdapter);

        // Prepare the loader.  Either re-connect with an existing one,
        // or start a new one.
        getLoaderManager().initLoader(0, null, this);
    }

    // Called when a new Loader needs to be created
    public Loader&lt;Cursor> onCreateLoader(int id, Bundle args) {
        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.
        return new CursorLoader(this, ContactsContract.Data.CONTENT_URI,
                PROJECTION, SELECTION, null, null);
    }

    // Called when a previously created loader has finished loading
    public void onLoadFinished(Loader&lt;Cursor> loader, Cursor data) {
        // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)
        mAdapter.swapCursor(data);
    }

    // Called when a previously created loader is reset, making the data unavailable
    public void onLoaderReset(Loader&lt;Cursor> loader) {
        // This is called when the last Cursor provided to onLoadFinished()
        // above is about to be closed.  We need to make sure we are no
        // longer using it.
        mAdapter.swapCursor(null);
    }

    &#64;Override 
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Do something when a list item is clicked
    }
}
</pre>

<p class="note"><strong>Note:</strong> Because this sample performs a query on the <a
href="{@docRoot}guide/topics/providers/contacts-provider.html">Contacts
Provider</a>, if you want to
try this code, your app must request the {@link android.Manifest.permission#READ_CONTACTS}
permission in the manifest file:<br/>
<code>&lt;uses-permission android:name="android.permission.READ_CONTACTS" /></code></p>