Friday, December 28, 2012

Android beginner tutorial: Part 34 - Custom rows in ListView

In this tutorial we'll learn how to create our own custom layout for a single row item in a list.

First we need to set up our activity_main.xml layout, which is a ListLayout. It will only contain the ListView:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
    
</LinearLayout>

I want the row items in the list to display the first and last names in two lines, where the first line is also bold.

To do this, we'll need to create a custom layout file and a custom class.

Let's start with the layout file. Using Eclipse IDE, go to File menu, select New and Android XML file. Walk through the wizard, make sure the file is identified as a "layout".

I named my new layout file customrow.xml.

After creating the file, add this code to it:

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical">

     <TextView android:id="@+id/text1"
         android:textSize="24sp"
         android:textStyle="bold"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"/>

     <TextView android:id="@+id/text2"
         android:textSize="24sp"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"/>
 </LinearLayout>

As you can see, it's a really simple layout, built the same way as the activity layouts. It has 2 TextViews, with ids text1 and text2, that are located one under another.

Now let's create a new Java class file. Go to File, New, Class. Name it CustomContact.

It's a class that extends HashMap, has 3 properties and a constructor. The HashMap class turns our CustomContact into a hash object, which is then useable as data provider.

The first variable is serialVersionUID - this is a system variable that you need to set unique for your custom classes. It has to be a "long" type variable (which translates to "long number"), so you can add "L" after the number. For example, "1L".

The other two variables are the ones defined by us - FIRST and LAST static strings with values "first" and "last".

In the constructor, receive 2 parameters - "first" and "last". Use the put() method of the super object to apply the value of the "first" parameter to the hash attribute with the FIRST name, and do the same for "last":

package com.kircode.codeforfood_test;

import java.util.HashMap;

public class CustomContact extends HashMap<String, String>{
private static final long serialVersionUID = 1L;
public static final String FIRST = "first";
public static final String LAST = "last";

public CustomContact(String first, String last){
super();
super.put(FIRST, first);
super.put(LAST, last);
}
}

Now go to MainActivity.java class.

Here, we don't need to declare any variables outside the constructor. Inside of it, however, declare an ArrayList type variable "contacts". Add objects to it using the add() method, but instead of strings, add CustomContact instances, with first and last names of the contacts provided as parameters of the constructor. Because the ArrayList contains CustomContacts, we write <CustomContact> after ArrayList.

Use the setListAdapter() method to apply a SimpleAdapter instance to the list activity. The SimpleAdapter class is an adapter that allows us to specifically tell the list activity what we want to display and how to do it.

We need to say what data provider to use, what layout to use for each item, what attributes to use from the objects to extract the data and what elements in the row layout to use to display the data.

Full code:

package com.kircode.codeforfood_test;

import java.util.ArrayList;

import android.app.ListActivity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.SimpleAdapter;

public class MainActivity extends ListActivity{

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ArrayList<CustomContact> contacts = new ArrayList<CustomContact>();
contacts.add(new CustomContact("Minnie", "Erdman"));
contacts.add(new CustomContact("Sean", "Marin"));
contacts.add(new CustomContact("Donald", "Reed"));
contacts.add(new CustomContact("Ann", "Heine"));
contacts.add(new CustomContact("Norman", "Hawks"));
contacts.add(new CustomContact("Luis", "Pollack"));
contacts.add(new CustomContact("Donald", "Rosemond"));
contacts.add(new CustomContact("Wayne", "Littlefield"));
contacts.add(new CustomContact("Sally", "Sayers"));
contacts.add(new CustomContact("Lisa", "Shotwell"));

setListAdapter(new SimpleAdapter(this, contacts, R.layout.customrow, new String[] {CustomContact.FIRST, CustomContact.LAST}, new int[] {R.id.text1, R.id.text2}));
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

}

And there we go.

The results:



Thanks for reading!

No comments:

Post a Comment