codeofaninja
website

Android Custom ListView Tutorial

Photo of Mike Dalisay
Modified Wednesday, February 20, 2013
by - @ninjazhai
Almost all Android apps uses ListView - showing list of records, settings, songs, articles, and many other types of data a certain app can handle. An Android ListView is simply a vertically scrollable list of items.

This tutorial will show you how to create a customized row in your ListView (with image and text). This is probably the simplest android ListView tutorial on the internet. Haha!

I remember using a ListView when I have to list records of location with its thumbnail, location name and date the data were taken.

android custom listview
Upper part of our ListView

Anyway, we are going to have Folders as our items on the list. Our code will have the following capability:

  • Include custom folder icon, folder name and description for each list item.
  • Show a toast when a user clicks on an item on the list (means we're going to have an onClickListener)

Code Download


You can download the code here: (If you're not familiar with Google Drive, you have to click on File > Download to download the code)

Android Custom ListView - download code

Files Needed


We are going to need only 2 JAVA files, 2 XML files and 3 custom icons.

Android Custom ListView - files needed
Highlighted are the files we'll create.

Let's Code!


activity_main.xml - Contains our ListView.
<?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:background="#FFFFFF"
    android:orientation="vertical" >

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

</LinearLayout>

listview_item_row.xml - the layout of each list item in our list view.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp" >

    <ImageView
        android:id="@+id/imageViewFolderIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:paddingRight="10dp"
        android:src="@drawable/folder" />

    <TextView
        android:id="@+id/textViewFolderName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/imageViewFolderIcon"
        android:text="Folder name here."
        android:textSize="20dp" />

    <TextView
        android:id="@+id/textViewFolderDescription"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textViewFolderName"
        android:layout_toRightOf="@+id/imageViewFolderIcon"
        android:text="Folder description here."
        android:textColor="#c5c5c5"
        android:textSize="14dp" />

</RelativeLayout>
It will look like this:

Android Custom ListView - ListItem output

-Folder Icon
     android:id="@+id/imageViewFolderIcon"
     android:layout_alignParentLeft="true"
     android:layout_alignParentTop="true"

-Folder Name
     android:id="@+id/textViewFolderName"
     android:layout_alignParentTop="true"
     android:layout_toRightOf="@+id/imageViewFolderIcon"

-Folder Description
     android:id="@+id/textViewFolderDescription"
     android:layout_below="@+id/textViewFolderName"
     android:layout_toRightOf="@+id/imageViewFolderIcon"

MainActivity.java - We have two classes in this file, first is the MainActivity where we set each of our list item data and second is the small Folder class that will take care of our list item data such as the folderIcon, folderName and folderDescription.

package com.example.androidlistview;

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

public class MainActivity extends Activity {

    private ListView listViewArticles;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /*
         * Data can be from your database. You have to know the number of list
         * items in advanced, in our example, we have 9
         */
        Folder[] folderData = new Folder[27];

        /*
         * @always start with index 0
         * 
         * @9 items in our list view.
         */
        folderData[0] = new Folder(R.drawable.icon_music_folder, "Usher", "My most favorite Usher songs.");
        folderData[1] = new Folder(R.drawable.icon_pictures_folder, "Family Images", "Pictures from different occasions.");
        folderData[2] = new Folder(R.drawable.icon_spreadsheet_folder, "Budget Spreadsheet", "My budget record every week.");
        folderData[3] = new Folder(R.drawable.icon_music_folder, "FM Static", "One of my most favorite bands.");
        folderData[4] = new Folder(R.drawable.icon_pictures_folder, "Outing - 2012", "Pictures in Boracay Island.");
        folderData[5] = new Folder(R.drawable.icon_spreadsheet_folder, "Business Spreadsheet", "Business accounts record.");
        folderData[6] = new Folder(R.drawable.icon_music_folder, "New Artists", "Cool songs by new artists.");
        folderData[7] = new Folder(R.drawable.icon_pictures_folder, "Anniversary - 2012", "Company party.");
        folderData[8] = new Folder(R.drawable.icon_spreadsheet_folder, "Credit Spreadsheet", "Credit records every month.");

        folderData[9] = new Folder(R.drawable.icon_music_folder, "Usher - 2", "My most favorite Usher songs - 2.");
        folderData[10] = new Folder(R.drawable.icon_pictures_folder, "Family Images - 2", "Pictures from different occasions - 2.");
        folderData[11] = new Folder(R.drawable.icon_spreadsheet_folder, "Budget Spreadsheet - 2", "My budget record every week - 2.");
        folderData[12] = new Folder(R.drawable.icon_music_folder, "FM Static - 2", "One of my most favorite bands - 2.");
        folderData[13] = new Folder(R.drawable.icon_pictures_folder, "Outing - 2012 - 2", "Pictures in Boracay Island - 2.");
        folderData[14] = new Folder(R.drawable.icon_spreadsheet_folder, "Business Spreadsheet - 2", "Business accounts record - 2.");
        folderData[15] = new Folder(R.drawable.icon_music_folder, "New Artists - 2", "Cool songs by new artists - 2.");
        folderData[16] = new Folder(R.drawable.icon_pictures_folder, "Anniversary - 2012 - 2", "Company party - 2.");
        folderData[17] = new Folder(R.drawable.icon_spreadsheet_folder, "Credit Spreadsheet - 2", "Credit records every month - 2.");
        
        folderData[18] = new Folder(R.drawable.icon_music_folder, "Usher - 3", "My most favorite Usher songs - 3.");
        folderData[19] = new Folder(R.drawable.icon_pictures_folder, "Family Images - 3", "Pictures from different occasions - 3.");
        folderData[20] = new Folder(R.drawable.icon_spreadsheet_folder, "Budget Spreadsheet - 3", "My budget record every week - 3.");
        folderData[21] = new Folder(R.drawable.icon_music_folder, "FM Static - 3", "One of my most favorite bands - 3.");
        folderData[22] = new Folder(R.drawable.icon_pictures_folder, "Outing - 2012 -3", "Pictures in Boracay Island - 3.");
        folderData[23] = new Folder(R.drawable.icon_spreadsheet_folder, "Business Spreadsheet - 3", "Business accounts record - 3.");
        folderData[24] = new Folder(R.drawable.icon_music_folder, "New Artists - 3", "Cool songs by new artists - 3.");
        folderData[25] = new Folder(R.drawable.icon_pictures_folder, "Anniversary - 2012 - 3", "Company party - 3.");
        folderData[26] = new Folder(R.drawable.icon_spreadsheet_folder, "Credit Spreadsheet - 3", "Credit records every month - 3.");
        
        // Pass the folderData to our ListView adapter
        FolderAdapter adapter = new FolderAdapter(this,
                R.layout.listview_item_row, folderData);

        // Set the adapter to our ListView
        listViewArticles = (ListView) findViewById(R.id.listView1);
        listViewArticles.setAdapter(adapter);

        /*
         * ListView item click listener. So we'll have the do stuff on click of
         * our ListItem
         */
        listViewArticles.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {

                // get the clicked folder name
                String listItemText = ((TextView) view
                        .findViewById(R.id.textViewFolderName))
                        .getText()
                        .toString();

                // just toast it
                Toast.makeText(MainActivity.this,
                        "You clicked: " + listItemText, Toast.LENGTH_LONG)
                        .show();

                // if you want to show a new screen or activity, you can call the intent here
            }
        });
    }

    /*
     * You can put this in another java file. This will hold the data elements
     * of our list item.
     */
    class Folder {

        public int folderIcon;
        public String folderName;
        public String folderDescription;

        // Constructor.
        public Folder(int folderIcon, String folderName,
                String folderDescription) {

            this.folderIcon = folderIcon;
            this.folderName = folderName;
            this.folderDescription = folderDescription;
        }
    }
}



FolderAdapter.java - This file will make the list items come true. We'll override the getView to set our customized data.

package com.example.androidlistview;

import com.example.androidlistview.MainActivity.Folder;

import android.app.Activity;
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;

public class FolderAdapter extends ArrayAdapter<Folder> {

    Context mContext;
    int layoutResourceId;
    Folder data[] = null;

    /*
     * @mContext - app context
     * 
     * @layoutResourceId - the listview_item_row.xml
     * 
     * @data - the ListItem data
     */
    public FolderAdapter(Context mContext, int layoutResourceId, Folder[] data) {

        super(mContext, layoutResourceId, data);
        this.layoutResourceId = layoutResourceId;
        this.mContext = mContext;
        this.data = data;
    }

    /*
     * @We'll overried the getView method which is called for every ListItem we
     * have.
     * 
     * @There are lots of different caching techniques for Android ListView to
     * achieve better performace especially if you are going to have a very long
     * ListView.
     * 
     * @convertView - the cache of list item row layout, if it is null, inflate new
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if(convertView==null){
            // inflate the listview_item_row.xml parent
            LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
            convertView = inflater.inflate(layoutResourceId, parent, false);
        }
        
        // get the elements in the layout
        ImageView imageViewFolderIcon = (ImageView) convertView.findViewById(R.id.imageViewFolderIcon);
        TextView textViewFolderName = (TextView) convertView.findViewById(R.id.textViewFolderName);
        TextView textViewFolderDescription = (TextView) convertView.findViewById(R.id.textViewFolderDescription);

        /*
         * Set the data for the list item. You can also set tags here if you
         * want.
         */
        Folder folder = data[position];

        imageViewFolderIcon.setImageResource(folder.folderIcon);
        textViewFolderName.setText(folder.folderName);
        textViewFolderDescription.setText(folder.folderDescription);

        return convertView;
    }

}



Output Screenshots


Android Custom ListView - lower part of our listview
Lower part of our ListView

Android Custom ListView - user clicks on an item
When user clicks on an item
"Budget Spreadsheet"

Further Readings


If you're loading your images from the internet, you might want to lazy load them for better ListView performance. You can use a library called LazyList.

If you want to see code example which focuses a bit on the adapter, see this post: Android ListView with Adapter Example

The Code of a Ninja Resources

For FREE programming tutorials, click the red button below and subscribe! :)
Thanks for the comments!
 
 
Fundamentals
"First do it, then do it right, then do it better."
~ Addy Osmani
"Talk is cheap. Show me the code."
~ Linus Torvalds
Let's Stay Connected!
g+ r
Android app on Google Play
© 2011-2014 The Code Of A Ninja. All rights reserved. Proudly Powered by Google Blogger. Images, logos, marks or names mentioned herein are the property of their respective owners.