|
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". 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. 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: 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. |