Two Line Lists In Android

A SimpleAdapter Loads a ListActivity with Two Line Entries

In the article Add a Simple List to an App example code was given to show how to load a ListActivity from a string array. This article shows how each list item in a ListActivity can display two lines of data, in this case each list item will be an American state and its capital. It is assumed that you know Java and that your computer is set up for Android development using Eclipse, if not see Set Up Windows for Android Development.

Start by creating a new Android Project in Eclipse using the File menu, select New then Android Project. Fill in the Project Name, here State Capitals is used. Click Next and select the build target from the installed APIs, e.g. Android 1.5, any of the installed APIs will work and it can be changed later if required. Click Next and enter the Package Name in the required format, e.g. biz.tekeye.statecapitals, leave Create Activity checked with the default Activity name, click Finish.

Overview

A common pattern in Android is to define a View in XML, set up the data that will be displayed in the View, then provide the code to load that data into the View. In the case of a ListView or ListActivity that code is provided by an Adapter. For a list with single line entries an ArrayAdapter does the job as seen in the previously mentioned article. Adding another line of data for each entry in the list requires the SimpleAdapter.

The code shown here will define a two dimensional string array to hold the American States names and capitals data. Two TextViews in a layout define the template for each list entry. The work of inflating the Views for each list entry and setting the values in the Views is done by a SimpleAdapter. An ArrayList and HashMap ensures the data goes into the correct TextView. This diagram summarises what the code achieves.

ListActivity and SimpleAdapter for Two Lines of Strings

Define the Data

Under the src folder in the project tree open the StateCapitalsActivity.java file. At the bottom of the class, just before the last closing brace (curly bracket), add a two dimensional string array to define our data. (See Copying Code from the Articles for tips). Here only a few values are shown, all fifty states are in the downloadable project code.

private String[][] StatesAndCapitals =
  {{"Alabama","Montgomery"},
   {"Alaska","Juneau"},
   {"Arizona","Phoenix"},
   {"Arkansas","Little Rock"},
   {"California","Sacramento"},
   {"Colorado","Denver"},
   {"Connecticut","Hartford"},
   {"Delaware","Dover"},
   {"Florida","Tallahassee"}};

Define the View for Each List Entry

To start with the Android built in layout for a two line list entry will be used (this will be changed later to show how it can be modified). The Android layout is available via android.R.layout.two_line_list_item.

Load an ArrayList with the Data and Keys via HashMaps

Each entry in the ArrayList is a HashMap, the HashMap links the data to each line in the list entry via a Key. The declaration of the ArrayList at the top of the class is:

ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();

Imports for ArrayList and HashMap are required. After the call to setContentView the string array is looped through and a HashMap created for each pair. The keys line1 and line2 are used. Each HashMap is added to the ArrayList:

HashMap<String,String> item;
for(int i=0;i<StatesAndCapitals.length;i++){
  item = new HashMap<String,String>();
  item.put( "line1", StatesAndCapitals[i][0]);
  item.put( "line2", StatesAndCapitals[i][1]);
  list.add( item );
} 

Create the SimpleAdapter

At the top of the class declare the SimpleAdapter (the import for SimpleAdapter will need to be added):

private SimpleAdapter sa;

It is configured after the code that loads the list:

 sa = new SimpleAdapter(this, list,
        android.R.layout.two_line_list_item,
        new String[] { "line1","line2" },
        new int[] {android.R.id.text1, android.R.id.text2});

Notice that the keys line1 and line2 are passed in as well as the View ids text1 and text2 (how do we know which ids to use, the developer documentation tells us). Extend the StateCapitalsActivity to be a ListActivity instead of standard Activity and call setListAdapter(sa); before the closing brace for onCreate (the import for ListActivity will be required). The full class looks like this (with imports shown):

import java.util.ArrayList;
import java.util.HashMap;
import android.app.ListActivity;
import android.os.Bundle;
import android.widget.SimpleAdapter;

public class CustomListActivity extends ListActivity {
  private SimpleAdapter sa;
  ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    HashMap<String,String> item;
    for(int i=0;i<StatesAndCapitals.length;i++){
      item = new HashMap<String,String>();
      item.put( "line1", StatesAndCapitals[i][0]);
      item.put( "line2", StatesAndCapitals[i][1]);
      list.add( item );
    }
    sa = new SimpleAdapter(this, list,
      android.R.layout.two_line_list_item ,
      new String[] { "line1","line2" },
      new int[] {android.R.id.text1, android.R.id.text2});
    setListAdapter( sa );
  }

  private String[][] StatesAndCapitals =
    {{"Alabama","Montgomery"},
     {"Alaska","Juneau"},
     {"Arizona","Phoenix"},
     {"Arkansas","Little Rock"},
     {"California","Sacramento"},
     {"Colorado","Denver"},
     {"Connecticut","Hartford"},
     {"Delaware","Dover"},
     {"Florida","Tallahassee"}};
}

Where is the actual ListView that will be used defined? The ListActivity class has its own ListView. To use it delete the setContentView(R.layout.main); line. Alternatively add a ListView to the current layout, here just before the TextView, giving it the id of list. Having a layout defined outside of the ListActivity allows you to add other controls before and after the ListView to support additional functionality. Here is res/layout/main.xml with a ListView added:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical" >
  <ListView android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:id="@+id/android:list"/>
  <TextView android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello" />
</LinearLayout>

Two Line List Example

Add Your Own Two Line Layout

You may want to change the look of the layout for each list entry. Do that by defining you own two line layout. (With the res\layout folder selected use the File menu and select New then Android XML File. Give the file a name, e.g. my_two_lines.xml, with LinearLayout as the root element select Finish.) The layout_height attribute is changed to wrap_content. Two TextViews are added with different ids from the default Android layout, just to show that they do not need to be text1 and text2. The first TextView for the states is in italics, the required font sizes and colors are added. Finally the TextView widths and heights are set to fill_parent and wrap_content. The layout should resemble this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical">
  <TextView android:id="@+id/line_a"
    android:textSize="14dp"
    android:textColor="#FFFFFF"
    android:textStyle="italic"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"/>
  <TextView android:id="@+id/line_b"
    android:textSize="12dp"
    android:textColor="#BFFF00"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"/>
</LinearLayout>

The setting up of the SimpleAdapter becomes:

sa = new SimpleAdapter(this, list,
    R.layout.my_two_lines,
    new String[] { "line1","line2" },
    new int[] {R.id.line_a, R.id.line_b});

Customised Two Line ListActivityAn example project is provided here for importing into Eclipse (importing from archives is covered in Move Android Code Between PCs Running Eclipse). It is also available from the Android Example Projects page.

9 thoughts on “Two Line Lists In Android

  1. Clear and simple tutorial, thank you!

    I have just one comment to your code, when defining ArrayList and HashMap, you are breaking encapsulation. You should use it like this:

    List<Map> list = new ArrayList<Map>();
    Map item = new HashMap();

    • Thank you.
      The declarations used are clear for less experienced programmers, particularly when calling the SimpleAdapter constructer, of course everyone can adapt the code to their preferred style.

    • Use json_encode in PHP to generate the string array as a json object on the website. Use URL to make a HTTP request with HttpURLConnection to get the json object (INTERNET permission must be requested) from the App. Parse the received string directly or using the Java JSON classes to generate the string array for the two line list.

  2. I would like to thank you for witting this tutorial. I am a newbie on Android and need to create and Android app for my final year project. You solved a problem that I had for 1 day now. With your help I was able to make progress in my project.

    The best tutorial ever.

  3. Awesome tutorial man.. Helped me a lot.. All other tutorials are like creating a class which extends ArrayAdapter or BaseAdapter.. This one is really good & simple to implement.. (Y)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Human Verification: In order to verify that you are a human and not a spam bot, please enter the answer into the following box below based on the instructions contained in the graphic.