ListView

ListView – Part 2

In part 1 of this series we got a simple ListView working. In this part we’ll look at how we handle clicks on items within the ListView and also look at managing things if we can’t extend ListActivity for any reason.

The next thing that we need to do is to handle click events. Let’s add a couple of methods to our ListViewActivity class:

[java] @Override
protected void onListItemClick( ListView l, View v, int position, long id )
{
TextView textView = (TextView) v.findViewById( android.R.id.text1 );
toast( (String) textView.getText() );
}

private void toast( String text )
{
Toast.makeText( ListViewActivity.this,
String.format( “Item clicked: %s”, text ), Toast.LENGTH_SHORT )
.show();
}
[/java]

The toast() method is simply a utility method to pop up a toast message. We’ll make further use of this in other examples so it makes sense to define a method.

The onListItemClick() method overrides a method in ListActivity and is another example of ListActivity making life easier for us. This will be called whenever the user clicks an item in the list. The arguments to this method are a the ListView in which the click event occurred, the View containing the layout of the clicked item, the position of the item within the ListAdapter (i.e. the index of the item within the data that we passed to the SimpleAdapter constructor), and a unique ID of the item (more about this later in the series).

All we’re doing here is finding the TextView within the layout View, and passing the text of that to our toast() method. This pops up a toast when we click an item:

An item click
An item click

This is all well and good, but what about if we can’t use ListActivity because we maybe need to inherit from a different Activity such as TabActivity if we use a tab control within our activity? For the sake of clarity, we’ll just change our example to extend Activity instead of ListActivity and we’ll immediately see two errors in or code:

  1. setListAdapter() is no longer available to us.
  2. onListItemClick() is no longer declared in the super class so the @override annotation causes the compiler to generate error accordingly.

The first error is fixed by finding the ListView control within the layout, and then setting the adapter on it directly:

[java] ListView listView = (ListView)findViewById( android.R.id.list );
listView.setAdapter( adapter );
[/java]

The second is fixed by setting an OnItemClickListener() instance on our ListView in our onCreate() method:

[java] listView.setOnItemClickListener( new OnItemClickListener()
{
@Override
public void onItemClick( AdapterView listView, View view,
int pos, long id )
{
TextView textView =
(TextView) view.findViewById( android.R.id.text1 );
toast( (String) textView.getText() );
}
} );
[/java]

So our onCreate() method now looks like this:

[java] @Override
public void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
setContentView( R.layout.main );

List> data = new ArrayList>();
for ( int i = 1; i <= 10; i++ ) { Map item = new HashMap();
item.put( “name”, String.format( “Item %d”, i ) );
data.add( item );
}

String[] from = { “name” };
int[] to = { android.R.id.text1 };

SimpleAdapter adapter = new SimpleAdapter( this, data,
android.R.layout.simple_list_item_1, from, to );

ListView listView = (ListView)findViewById( android.R.id.list );
listView.setAdapter( adapter );

listView.setOnItemClickListener( new OnItemClickListener()
{

@Override
public void onItemClick( AdapterView listView, View view,
int pos, long id )
{
TextView textView = (TextView) view.findViewById( android.R.id.text1 );
toast( (String) textView.getText() );
}
} );
}
[/java]

We also need to remove the onListItemClick() method.

This produces the same result as before only we’re no longer using ListActivity.

The one exception is that we no longer get the empty list handling that ListActivity provided us. This is somewhat meaningless for our example as there will always be items in our adapter because it is simply static data. However if you have an adapter which wraps dynamic data which calls notifyDataSetChanged() on the adapter when it changes then we need to detect any changes to our adapter by calling it’s registerDataSetObserver() method to register a DataSetObserver . This will get called whenever the data underlying the adapter changes and calls notifyDataSetChanged(). Whenever this happens the onChanged() method of our DataSetObserver will be called and we should override this method to perform a check to see if the data set is empty. If it is, we should show the TextView which has the id android.R.id.empty and hide the ListView which has the id android.R.id.list. If the data set is not empty we reverse the visibility of these two controls. I haven’t included this code in the example for the simple reason that I want to keep the example code clear, succinct, and relevant, but it is relatively easy to add this behaviour if you require it.

In the next part of this series we’ll look at using more complex layouts for each list item.

The source code for this article can be found here.

UPDATE: As per Audrius’ comment, you can perform the empty list management by using setEmptyView() on your ListView.

© 2011, Mark Allison. All rights reserved.

Copyright © 2011 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at http://blog.stylingandroid.com/license-information.

5 Comments

  1. Another way to handle empty listviews is by adding view next to ListView control (with id) and then calling [your listview control here].setEmptyView([empty view control]). Some say that if your empty view id is android.id.empty then all of this is automatically handled by Android OS, but I had no such luck.

  2. hello,
    i want to put

    ——————
    | textView1 |
    | textView2 |
    ——————-

    three times this view should be printed
    and i want background cloor white n text color which layout shud i use?

    1. Sorry, I don’t have any bandwidth to provide developer support. I would recommend stackoverflow.com if you have specific problems that you require help with.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.