Getting to First Base

The classic Android ListView is a plain list of text—solid but uninspiring. This is because all we hand to the ListView is a bunch of words in an array, and we tell Android to use a simple built-in layout for pouring those words into a list.

However, you can have a list whose rows are made up of icons, or icons and text, or checkboxes and text, or whatever you want. It is merely a matter of supplying enough data to the adapter and helping the adapter to create a richer set of View objects for each row.

For example, suppose you want a ListView whose entries are made up of an icon, followed by some text. You could construct a layout for the row that looks like this, found in the FancyLists/ Static sample project available in the Source Code section of the Apress Web site:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="" android:layout width="fill parent" android:layout height="wrap content" android:orientation="horizontal"

<ImageView android:id="@+id/icon" android:layout width="22px" android:paddingLeft="2px" android:paddingRight="2px" android:paddingTop="2px" android:layout height="wrap content" android:src="@drawable/ok"

<TextView android:id="@+id/label" android:layout width="wrap content" android:layout height="wrap content" android:textSize="44sp"


This layout uses a LinearLayout to set up a row, with the icon on the left and the text (in a nice big font) on the right.

By default, though, Android has no idea that you want to use this layout with your ListView. To make the connection, you need to supply your Adapter with the resource ID of the custom layout shown in the preceding code:

public class StaticDemo extends ListActivity { TextView selection;

String[] items={"lorem", "ipsum", "dolor", "sit", "amet",

"consectetuer", "adipiscing", "elit", "morbi", "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam", "vel", "erat", "placerat", "ante", "porttitor", "sodales", "pellentesque", "augue", "purus"};

@Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); setListAdapter(new ArrayAdapter<String>(this, R.layout.row,, items));


public void onListItemClick(ListView parent, View v, int position, long id) { selection.setText(items[position]);

This follows the general structure for the previous ListView sample. The key in this example is that you have told ArrayAdapter that you want to use your custom layout (R.layout.row) and that the TextView where the word should go is known as within that custom layout. Remember: to reference a layout (row.xml), use R.layout as a prefix on the base name of the layout XML file (R.layout.row).

The result is a ListView with icons down the left side. In particular, all the icons are the same, as Figure 9-1 shows.

This technique—supplying an alternate layout to use for rows—handles simple cases very nicely. However, it isn't sufficient when you have more-complicated scenarios for your rows, such as the following:

• Not every row uses the same layout (e.g., some have one line of text, others have two).

• You need to configure the widgets in the rows (e.g., different icons for different cases).

In those cases, the better option is to create your own subclass of your desired Adapter, override getView(), and construct your rows yourself. The getView() method is responsible for returning a View, representing the row for the supplied position in the adapter data.

For example, let's rework the preceding code to use getView() so we can have different icons for different rows—in this case, one icon for short words and one for long words (from the FancyLists/Dynamic sample project at

public class DynamicDemo extends ListActivity { TextView selection;

String[] items={"lorem", "ipsum", "dolor", "sit", "amet",

"consectetuer", "adipiscing", "elit", "morbi", "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam", "vel", "erat", "placerat", "ante", "porttitor", "sodales", "pellentesque", "augue", "purus"};

Figure 9-1. The StaticDemo application
0 -1

Post a comment