Today I'm going to go step by step through an example of using a ListView, and customizing the visual layout of items within. ListView is one of the primary UI components in the Android SDK. Its a great tool, providing you with scrolling lists and selection functionality right out of the box. With very little code, you can have a ListView displaying a list of objects for you. Just toss something like
in your layout file (e.g. main.xml, for a simple application), and something like
on the java side in your onCreate() method. Easy, huh? Running this application will produce the following:
This may look a bit complicated, but its really not. This xml will just define the layout of our items, so each selection in the ListView will have this layout within it. We've created a linear layout as our root layout (note: since we didn't specify, this layout will have a horizontal orientation for components inside of it). Inside of this base structure, we have two sub-components: an ImageView, which will display a single image, and a LinearLayout components with a vertical orientation. In this inner LinearLayout, we have two TextView components. This will display two text fields, one on top of the other, horizontally adjacent to the ImageView. Take a look at the ImageView definition. We have to tell the ImageView what image it will display. We tell it this with the android:src parameter. For simplicity, we are giving this a value of "@drawable/icon", which will tell it to use a file named icon.* (any image extension) found in one of the "res/drawable-*" directories. This icon file is included in any new android project created through eclipse, making it an easy target - you could just as easily point it at any image file you chose to put in these directories. In a real application to display user avatars, we would want to change this value in our java code to place a different avatar image in each ListView item. Now we just have to create a new Adapter class that will tell our ListView how to user this new item layout. To make things easier, I'll first create a small UserRecord class to allow us to pass our user item data around easily. Here it is:
Now for the adapter, which is a bit more complex:
So what are we doing here? Let's take a look. We are creating an adapter class which extends ArrayAdapter, meaning this adapter will take an array of UserRecord objects as input. In the constructor, we just call the superclass constructor to handle any background initialization issues that we don't want to worry about, and take the list of UserRecords given as an input parameter and save it to a local variable for safekeeping. The main thing we are doing here is overriding the getView() method with our own version - this will allow us to specify how to set the values of the UI components ourselves, since we are the ones who created this UI layout. When our app is displaying a ListView, it will call getView() for each item in the input array. getView() takes three parameters:
int position - the position of the item in the array we want to display
a View - the view that will display the item in question
a ViewGroup parent - the group our view belongs to. We won't need to deal with this for the task at hand. We do a little handling at the top in case the View object passed in is null (it shouldn't be in this example), and then we can set some values. Since we grabbed the list of UserRecord objects and stored it in a member variable in the UserItemAdapter constructor, we just get the objects at the specified position to have access to all of the values we want (just username and email, here, but obviously it could be much more data). Using a few findViewById() calls on our View, we get the UI components (TextView objects, in this case) that we want to use to displat our data, and set their text values using the specified UserRecord object. Return the View, and viola! Our ListView now looks like: