Arduino Uno

Header

Corner

ListView

This page is about creating a custom ListView, including a custom ArrayAdapter.

Let's suppose we would like to have a list of persons. We first have to write a class Person. A quick and dirty way is to put all fields visibility to public, which is not that good, but it's enough for the example right now.

public class Person {
	public String lastname	= "John";
	public String firstname	= "Smith";
	public boolean friend   = false;
}

Next we need to add a new XML layout file. This file will describe a single item of the list. After chosing "New" from the contextual menu op "Layout", chose "Other", then "Android XML Layout File".

Add XML Layout file

I named the file "listview_item" and chose as root layout the "RelativeLayout", but you may adapt this to your needs.

Now you can go ahead and populate the layout. I've added an image named friendImage as well as two editable textfields firstnameTextEdit and lastnameTextEdit. The image indicates if this is a friend of not.

Layout of one item

In the next step, we need to define the adapter. This is the stuff that communicates between our data structure and the visible list.

package com.example.listviewdemo;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.app.Activity;

public class PersonAdapter extends ArrayAdapter
{
    Context context;
    int layoutResourceId; 
    // the list will hold a reference to the entire data structure
    ArrayList data = null;
   
    public PersonAdapter(Context context, int layoutResourceId, ArrayList data) 
    {
        super(context, layoutResourceId, data);
        this.layoutResourceId = layoutResourceId;
        this.context = context;
        this.data = data;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
    {
        View row = convertView;
        PersonHolder holder = null;
       
        if(row == null)
        {
        	// this will inflate the XML layout to the row
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);
           
            holder = new PersonHolder();
            // get the references to the persons list information
            holder.firstname = (TextView)row.findViewById(R.id.firstnameEditText);
            holder.lastname  = (TextView)row.findViewById(R.id.lastnameEditText);
            holder.friend    = (ImageView) row.findViewById(R.id.friendImage);

            row.setTag(holder);
        }
        else
        {
            holder = (PersonHolder)row.getTag();
        }
       
        // get the person
        Person person = data.get(position);
        // fill the list items
        holder.firstname.setText(person.firstname);
        holder.lastname.setText(person.lastname);
        if(person.friend) holder.friend.setImageResource(android.R.drawable.btn_star_big_on);
        else   		 	  holder.friend.setImageResource(android.R.drawable.btn_star_big_off);

        return row;
    }    

    /**
     * a static data class to hold a persons information as show in the list
     */
    static class PersonHolder
    {
        TextView firstname;
        TextView lastname;
        ImageView friend;
    }
}

Last but not least, supposing that you have added a ListView widget to your main activity and called it listView, the following code populates the list.

		// create the list of persons
		ArrayList persons = new ArrayList();
		persons.add(new Person()); // default one
		Person p = new Person(); p.firstname="Bill"; p.lastname="Deer"; p.friend=true;
		persons.add(p);
		// get a reference to our ListView
		ListView listView = (ListView) findViewById(R.id.listView);
		// create the PersonAdapter, liking the data structure and the item layout to the ListView
		PersonAdapter adapter = new PersonAdapter(MainActivity.this,R.layout.listview_item, persons);
		// apply the adatper
        listView.setAdapter(adapter);

Remember that it has to be executed on the main thread! So if your in some other thread - possibly because you're getting the data from the network or somewhere else asynchrously - you may want to write something like this:

// define a runnable
Runnable r = new Runnable() 
{
	@Override
	public void run() 
	{
		// update GUI elements
		//... your code here
	}
};
// make it start on the UI thread
runOnUiThread(r);

Finally, when launching this app, you should end up with something like this:

ListView Demo

Okay, so now it's up to you to apply this to your own data, design you own item layout and put it all together just the way you need it.