Android ListView Items with Custom Adapter
In this tutorial, it will help you to know
about Custom Adapter and ListView.
Create a new Android project in Eclipse with MainActivity as your default Activity and main.xml as your default layout file. Declare a ListView control in your main.xml layout file as shown in the following code.
Main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFFF">
<ListView
android:id="@+id/listView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
The above code is using simple LinearLayout with vertical orientation, and a ListView is declared to cover the entire width and height of the parent container using the fill_parent as the value of both android:layout_heightand android:layout:width properties. ListView also has a unique id listView1 that will be used in the MainActivity to reference the ListView control.
To create the custom header for the ListView, create a new xml layout file main_header.xml in the layout folder of your project and declare a TextView control in it with the properties shown in the following code. This will create a blue header with the white color text showing Contacts.
Main_header.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/txtHeader"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textStyle="bold"
android:textSize="22dp"
android:textColor="#FFFFFF"
android:padding="10dp"
android:text="Contacts"
android:background="#336699" />
</LinearLayout>
To create a custom ListView row, create another xml layout file listview_item_row.xml in the project layout directory. Android will render this file content in every ListView item and you are free to declare any control you want in it. For this tutorial I am using an ImageView for an icon and a TextView for displaying items titles. Following is the code for listview_item.xml file.
Listview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="@drawable/email_icon" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/imageView1"
android:layout_marginLeft="22dp"
android:layout_toRightOf="@+id/imageView1"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
Next create a new Java class in your project and named it Contacts.java. This class will be used to create a custom ArrayAdapter and to bind the objects with the ListView later in this tutorial. Following is the code of Contacts.java class. It has two simple properties icon and title and a typical class constructor to initialize the properties.
public class Contacts
{
public int icon;
public String title;
public Contacts() {
super();
// TODO Auto-generated constructor stub
}
public Contacts(int icon, String title) {
super();
this.icon = icon;
this.title = title;
}
}
Notice that the above listview_item.xml file has two views, which are correspondent to the properties of the Contacts class. The values of the Weather class properties will be displayed on those views and to connect these two pieces together you need to create a custom ArrayAdapter that will inherit the Android ArrayAdapter class and will override the getView method. Add a new java class in your project with the name ContactsAdapter and implement the code as shown below:
public class ContactsAdapter extends ArrayAdapter<Contacts>
{
Context context;
int layoutResourceId;
Weather data[] = null;
public ContactsAdapter(Context context, int layoutResourceId, Contacts[] data)
{
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View row = convertView;
ContactsHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ContactsHolder();
holder.imgIcon = (ImageView)row.findViewById(R.id.imageView1);
holder.txtTitle = (TextView)row.findViewById(R.id.textView1);
row.setTag(holder);
}
else
{
holder = (ContactsHolder)row.getTag();
}
Contacts con = data[position];
holder.txtTitle.setText(con.title);
holder.imgIcon.setImageResource(con.icon);
return row;
}
static class ContactsHolder
{
ImageView imgIcon;
TextView txtTitle;
}
}
In the above code, the first important thing is the constructor of the class that takes three parameters. The first parameter is the Context and we can pass the reference of the activity in which we will use ContactsAdapterclass. The second parameter is the resource id of the layout file we want to use for displaying each ListView item. We will pass the resource id of our layout file listview_item.xml for this parameter. The third parameter is an array of Contacts class objects that will be used by the Adapter to display data.
Next the parent class getView method is overridden. This method will be called for every item in the ListView to create views with their properties set as we want. The getView method is also using a temporary holder class declared inside the ContactsAdapter class. This class will be used to cache the ImageView and TextView so they can be reused for every row in the ListView and this will provide us a great performance improvement as we are recycling the same two views with different properties and we don’t need to find ImageView and TextView for every ListView item. The above code is also using the Android built in Layout Inflator to inflate (parse) the xml layout file.
The final piece of code is our application MainActivity in which we will be using all the above objects we declared. Following is the code of the Home.java file.
public class Home extends Activity {
private ListView lv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Contacts data[] = new Contacts[]
{
new Contacts(R.drawable.email_icon,"Tara"),
new Contacts(R.drawable.email_icon,"Neo")
};
ContactsAdapter adapter = new ContactsAdapter(this, R.layout.listview_item, data);
lv = (ListView)findViewById(R.id.listView1);
View header = (View)getLayoutInflater().inflate(R.layout.main_header, null);
lv.addHeaderView(header);
lv.setAdapter(adapter);
}
}
Now You run this program & see Output: