Building a Custom Multi-Line ListView in Android

This tutorial will walk you through building a custom multi-line ListView in Android.

We’ll achieve this by extending BaseAdapter (or concrete ArrayAdapter) to turn a collection of objects into individual ListView items.

First, let’s define the layout for our scrollable ListView by placing the following in main.xml:
[xml]
<?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" >

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:text="Custom ListView Example" />

<ListView
android:id="@+id/srListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

</LinearLayout>
[/xml]

Next, let’s define a layout for individual ListView items. Paste this layout code in a new layout file called custom_row_view.xml:
[xml]
<?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"
android:paddingBottom="10dip"
android:paddingLeft="10dip"
android:paddingTop="10dip" >

<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#C20000"
android:textSize="14sp"
android:textStyle="bold" />

<TextView
android:id="@+id/cityState"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>
[/xml]

Next, let’s create a POJO called SearchResults.java to represent contact search results. Paste this boilerplate code into it:
[java]
package com.publicstaticdroidmain.android;

public class SearchResults {
private String name = "";
private String cityState = "";
private String phone = "";

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setCityState(String cityState) {
this.cityState = cityState;
}

public String getCityState() {
return cityState;
}
public void setPhone(String phone) {
this.phone = phone;
}

public String getPhone() {
return phone;
}
}
[/java]

Now we need to build an Adapter. The Adapter will turn our collection of SearchResults into individual ListView items. Create a file called MyCustomBaseAdapter.java with these contents:
[java]
package com.publicstaticdroidmain.android;

import java.util.ArrayList;

import com.publicstaticdroidmain.R;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class MyCustomBaseAdapter extends BaseAdapter {
private static ArrayList<SearchResults> searchArrayList;

private LayoutInflater mInflater;

public MyCustomBaseAdapter(Context context, ArrayList<SearchResults> results) {
searchArrayList = results;
mInflater = LayoutInflater.from(context);
}

public int getCount() {
return searchArrayList.size();
}

public Object getItem(int position) {
return searchArrayList.get(position);
}

public long getItemId(int position) {
return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.custom_row_view, null);
holder = new ViewHolder();
holder.txtName = (TextView) convertView.findViewById(R.id.name);
holder.txtCityState = (TextView) convertView
.findViewById(R.id.cityState);
holder.txtPhone = (TextView) convertView.findViewById(R.id.phone);

convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}

holder.txtName.setText(searchArrayList.get(position).getName());
holder.txtCityState.setText(searchArrayList.get(position)
.getCityState());
holder.txtPhone.setText(searchArrayList.get(position).getPhone());

return convertView;
}

static class ViewHolder {
TextView txtName;
TextView txtCityState;
TextView txtPhone;
}
}
[/java]

And finally, let’s update our main Activity class (mine is called CustomListViewActivity) to tie everything together:
[java]
package com.publicstaticdroidmain.android;

import java.util.ArrayList;

import com.publicstaticdroidmain.R;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;

public class CustomListViewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

ArrayList<SearchResults> searchResults = GetSearchResults();

final ListView lv = (ListView) findViewById(R.id.srListView);
lv.setAdapter(new MyCustomBaseAdapter(this, searchResults));

lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Object o = lv.getItemAtPosition(position);
SearchResults fullObject = (SearchResults)o;
Toast.makeText(CustomListViewActivity.this, "You have chosen: " + " " + fullObject.getName(), Toast.LENGTH_LONG).show();
}
});
}

private ArrayList<SearchResults> GetSearchResults(){
ArrayList<SearchResults> results = new ArrayList<SearchResults>();

SearchResults sr = new SearchResults();
sr.setName("Justin Schultz");
sr.setCityState("San Francisco, CA");
sr.setPhone("415-555-1234");
results.add(sr);

sr = new SearchResults();
sr.setName("Jane Doe");
sr.setCityState("Las Vegas, NV");
sr.setPhone("702-555-1234");
results.add(sr);

sr = new SearchResults();
sr.setName("Lauren Sherman");
sr.setCityState("San Francisco, CA");
sr.setPhone("415-555-1234");
results.add(sr);

sr = new SearchResults();
sr.setName("Fred Jones");
sr.setCityState("Minneapolis, MN");
sr.setPhone("612-555-8214");
results.add(sr);

sr = new SearchResults();
sr.setName("Bill Withers");
sr.setCityState("Los Angeles, CA");
sr.setPhone("424-555-8214");
results.add(sr);

sr = new SearchResults();
sr.setName("Donald Fagen");
sr.setCityState("Los Angeles, CA");
sr.setPhone("424-555-1234");
results.add(sr);

sr = new SearchResults();
sr.setName("Steve Rude");
sr.setCityState("Oakland, CA");
sr.setPhone("515-555-2222");
results.add(sr);

sr = new SearchResults();
sr.setName("Roland Bloom");
sr.setCityState("Chelmsford, MA");
sr.setPhone("978-555-1111");
results.add(sr);

sr = new SearchResults();
sr.setName("Sandy Baguskas");
sr.setCityState("Chelmsford, MA");
sr.setPhone("978-555-2222");
results.add(sr);

sr = new SearchResults();
sr.setName("Scott Taylor");
sr.setCityState("Austin, TX");
sr.setPhone("512-555-2222");
results.add(sr);

return results;
}
}
[/java]

And that’s it. If you’ve done everything correctly, you should wind up with this:

Android Custom Multi-Line ListView Screenshot
Android Custom Multi-Line ListView Screenshot

Here’s the zipped source code.


Posted

in

by

Comments

6 responses to “Building a Custom Multi-Line ListView in Android”

  1. HB Avatar
    HB

    Thanks for the tutorial.

    Managed to incorporate multi line text into my ListFragment – just what I needed, so thank you.

    I searched for “android multiline listview” if that helps you at all. Came up No. 1.

  2. danny Avatar
    danny

    thanks. it will be nice if you could include images to the listview?

    like the one here:
    http://android-developers.blogspot.com/2009/02/android-layout-tricks-1.html

    thank you!

  3. Josette Avatar

    Hi there, after reading this remarkable piece of writing i am too cheerful tto share my
    know-how here with mates.

    Here is my web page … Josette

  4. 通りかかる 意味 Avatar

    Both rock climbing and skydiving have a component of danger.
    Rock climbing is just a little like skydiving. What kind
    of rock climbing is safer, sooner and less expensive than traditional climbing?

  5. bo slot gacor Avatar

    I’ve been exploring f᧐r а lіttle bit fοr any higһ-quality articles οr blog posts іn thiѕ sort оf space .
    Exploring in Yahoo І finaⅼly stumbled սpon this webb site.
    Studying tһis infοrmation So і аm glad to convey tһɑt I
    һave an incredibly excellent uncanny feeling І fοund out just ᴡhat
    I needed. I most no doubt wilⅼ make ssure to do not
    omit this web site and provides іt a look on a continuing basis.

    mу homepage – bo slot gacor

  6. situs togel terpercaya Avatar

    I blog frequently annd І trulʏ apprеciate your infօrmation. Thiis ցreat article has tгuly peaked
    my interest. I am going to book mark yօur blog and keep checking fоr neᴡ infoгmation abot
    once per week. I subscribed tο your RSS feed too.

    My webpage; situs togel terpercaya

Leave a Reply

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