Android: Custom ListView with Image and Text using ArrayAdapter

8 September 2012 By Nithya Vasudevan 124,110 views 47 Comments
87 Flares Twitter 3 Facebook 57 Google+ 27 87 Flares ×

Project Description

  • In the previous Android 4 example, we created ListView in XML layout and populate its items from string array defined by external resource (res/values/strings.xml) programatically using simple ArrayAdapter.
  • In this Android 4 example, we will create custom ListView where each row item consists of one ImageView and two TextView (one for displaying image title and other for displaying image description) and populate its items using custom ArrayAdapter.
  • Job of an Adapter:
    • defines how each row is displayed (i.e) the layout for each row. We will define layout for rows in ListView in a XML file and place it in res/layout.
    • provides data to each row in ListView.
  • Here, we are going to implement OnItemClickListener event listener which calls onItemClick() callback method where we retrieve and display the item selected by the user.

Environment Used

  • JDK 6 (Java SE 6)
  • Eclipse Indigo IDE for Java EE Developers (3.7.2)
  • Android SDK 4.0.3 / 4.1 Jelly Bean
  • Android Development Tools (ADT) Plugin for Eclipse (ADT version 20.0.0)
  • Refer this link to setup the Android development environment or this link to update to a latest version of Android SDK

Prerequisites

Create Android Project

Create a new Android Project

strings.xml

Open res/values/string.xml and replace it with following content.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, ImageTextListViewActivity!</string>
    <string name="app_name">SimpleImageTextListView</string>
    <string name="name">ListViewBaseAdapter</string>
    <string name="image">Thumbnail</string>
</resources>

XML layout files

Main Activity layout XML (main.xml)

Open main.xml file in res/layout and copy the following content.

<?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:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
     />
</LinearLayout>

ListView Row layout XML (list_item.xml)

Create a new XML file list_item.xml in res/layout and copy the following content.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <ImageView
        android:id="@+id/icon"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:contentDescription="@string/image"
        android:paddingLeft="10dp"
        android:paddingRight="10dp" />

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/icon"
        android:paddingBottom="10dp"
        android:textColor="#CC0033"
        android:textSize="16dp" />

    <TextView
        android:id="@+id/desc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/title"
        android:layout_toRightOf="@+id/icon"
        android:paddingLeft="10dp"
        android:textColor="#3399FF"
        android:textSize="14dp" />
</RelativeLayout>

Bean class

Create a new class “RowItem” in “com.theopentutorials.android.beans” package and copy the following code. This class is used to store the data for each row in ListView.

package com.theopentutorials.android.beans;
public class RowItem {
	private int imageId;
	private String title;
	private String desc;
	
	public RowItem(int imageId, String title, String desc) {
		this.imageId = imageId;
		this.title = title;
		this.desc = desc;
	}
	public int getImageId() {
		return imageId;
	}
	public void setImageId(int imageId) {
		this.imageId = imageId;
	}
	public String getDesc() {
		return desc;
	}
	public void setDesc(String desc) {
		this.desc = desc;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	@Override
	public String toString() {
		return title + "\n" + desc;
	}	
}

Custom ArrayAdapter class

Create a new class “CustomListViewAdapter” in “com.theopentutorials.android.adapters” package and copy the following code. This class extends android.widget.ArrayAdapter to provide custom row layout and data for ListView.

package com.theopentutorials.android.adapters;

import java.util.List;
import com.theopentutorials.android.R;
import com.theopentutorials.android.beans.RowItem;
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 CustomListViewAdapter extends ArrayAdapter<RowItem> {

	Context context;

	public CustomListViewAdapter(Context context, int resourceId,
			List<RowItem> items) {
		super(context, resourceId, items);
		this.context = context;
	}
	
	/*private view holder class*/
	private class ViewHolder {
		ImageView imageView;
		TextView txtTitle;
		TextView txtDesc;
	}
	
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder = null;
		RowItem rowItem = getItem(position);
		
		LayoutInflater mInflater = (LayoutInflater) context
				.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
		if (convertView == null) {
			convertView = mInflater.inflate(R.layout.list_item, null);
			holder = new ViewHolder();
			holder.txtDesc = (TextView) convertView.findViewById(R.id.desc);
			holder.txtTitle = (TextView) convertView.findViewById(R.id.title);
			holder.imageView = (ImageView) convertView.findViewById(R.id.icon);
			convertView.setTag(holder);
		} else 
			holder = (ViewHolder) convertView.getTag();
				
		holder.txtDesc.setText(rowItem.getDesc());
		holder.txtTitle.setText(rowItem.getTitle());
		holder.imageView.setImageResource(rowItem.getImageId());
		
		return convertView;
	}
}

Activity class

Create a new class “ImageTextListViewActivity” in “com.theopentutorials.android.activities” package and copy the following code.

package com.theopentutorials.android.activities;

import java.util.ArrayList;
import java.util.List;
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;
import com.theopentutorials.android.R;
import com.theopentutorials.android.adapters.CustomListViewAdapter;
import com.theopentutorials.android.beans.RowItem;

public class ImageTextListViewActivity extends Activity implements
		OnItemClickListener {

	public static final String[] titles = new String[] { "Strawberry",
			"Banana", "Orange", "Mixed" };

	public static final String[] descriptions = new String[] {
			"It is an aggregate accessory fruit",
			"It is the largest herbaceous flowering plant", "Citrus Fruit",
			"Mixed Fruits" };

	public static final Integer[] images = { R.drawable.straw,
			R.drawable.banana, R.drawable.orange, R.drawable.mixed };

	ListView listView;
	List<RowItem> rowItems;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		rowItems = new ArrayList<RowItem>();
		for (int i = 0; i < titles.length; i++) {
			RowItem item = new RowItem(images[i], titles[i], descriptions[i]);
			rowItems.add(item);
		}

		listView = (ListView) findViewById(R.id.list);
		CustomListViewAdapter adapter = new CustomListViewAdapter(this,
				R.layout.list_item, rowItems);
		listView.setAdapter(adapter);
		listView.setOnItemClickListener(this);
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		Toast toast = Toast.makeText(getApplicationContext(),
			"Item " + (position + 1) + ": " + rowItems.get(position),
			Toast.LENGTH_SHORT);
		toast.setGravity(Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);
		toast.show();
	}
}

The above code works as follows;

  • For simplicity, we have hard-coded the row data (title, description, image id).
  • Creates a list of RowItems and stores these row data object.
  • Creates an object for custom ArrayAdapter and passes the list of RowItems.
  • Sets this adapter in the ListView.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.theopentutorials.android"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".activities.ImageTextListViewActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
   </application>
</manifest>

Output

Run your application

Project Folder Structure

The complete folder structure of this example is shown below.

Tags: , , , , , , , , , , ,

  • Pingback: The right coding approach for ListView with Images and Text? | Jisku.com

  • Manoj

    Simply superb, nice and smooth example

  • Narendra

    Good one.

  • Nico

    I like everything about it, the only problem i have is that my list is only show the first item.

    I am using asynctask, getting the data is not a problem (using a webservice) just updating the view is the problem.

    if i change the orientation to landscape and scroll it shows the item that are currently not on the screen showing, when i scroll down the top two rows cannot be seen(remember only the first one is showing the second one is empty).
    After i scroll back up the 2nd item now shows up in the list.

    I have tried many things such as: adapter.notifyDataSetChanged();
    listView.refreshDrawableState();
    listView.requestLayout();

    none of them work; here is a snippet
    of the onPostExecute:

    //Get after data has been gathered from doinginBackground procedure pass the arraylist to be shown
    @SuppressWarnings(“deprecation”)
    protected void onPostExecute(ArrayList val) {
    super.onPostExecute(val);
    dismissDialog(DIALOG_ID);
    try {
    if (val.size() > 1) {

    // for(Rate y: x){
    for (int i = 0; i < val.size(); i++) {

    RowItem item = new RowItem(R.drawable.rihanna,
    String.valueOf(val.get(i).getGasRate()), val
    .get(i).getDateModified()
    .toLocaleString());
    rowItems.add(item);
    }

    CustomListViewAdapter adapter = new CustomListViewAdapter(
    getApplicationContext(), R.layout.list_row,
    rowItems);
    listView.setAdapter(adapter);
    adapter.notifyDataSetChanged();
    listView.refreshDrawableState();
    Toast.makeText(getApplicationContext(), "Rates Updated",
    Toast.LENGTH_SHORT).show();
    } else {
    Toast.makeText(getApplicationContext(),
    "Rates Updated Failed", Toast.LENGTH_SHORT).show();
    }
    } catch (Exception e) {
    Toast.makeText(getApplicationContext(), e.toString(),
    Toast.LENGTH_LONG).show();
    }
    }

    • Karthik

      11-16 14:03:01.685: E/AndroidRuntime(4774): FATAL EXCEPTION: main
      11-16 14:03:01.685: E/AndroidRuntime(4774): java.lang.NullPointerException
      11-16 14:03:01.685: E/AndroidRuntime(4774): at com.customlist.CustomListAdapter.getView(CustomListAdapter.java:43)
      Hi..
      I’m a newbie..i am getting this kind of error..dont know how to get it solved..plz do help me out.Thanks

  • Karthika

    Hi,
    Thanks for your example.Its simple.I tried this but the one didn’t work is the onItemClickListener.If i click on the items in the list it doesn’t call onItemClick().
    Please help…

  • gunalan88

    Hi Friends,

    I am newbie to android development.

    I am now developing a tab widget example with 4 tabs with custom list view example in one of the tab.
    Problem: I have created the custom list view example with the help of following url.

    http://theopentutorials.com/tutorials/android/listview/android-custom-listview-with-image-and-text-using-arrayadapter/

    I have changed necessary changes in files.

    But the custom list view didn’t appear in the specified tab.

    Note:
    If this information is not sufficient, please reply me, what I have to give?

  • Pradnya

    Simple and Superb example!

  • http://sagartrehan.in Sagar Trehan

    Hi,

    Thank you very much.Your post is just wonderful.
    Your post done a lot of work for me.

  • Ajaxian

    Thanks a lot!!!!
    Very useful sample to begin understanding Adapters and List Views.
    It help me a lot

  • mero

    Superb tutorial works like a charm :)
    kindly tell me how should I incoporate multiple selection with a checkbox?

    • http://theopentutorials.com Nithya Vasudevan

      You can refer this link for multiple selection listview with checkbox.

  • emran

    Simple and Superb example!

  • Srinivas

    I tried to implement this code in a list fragment and I am unable to get a listview instance. It gives me a null pointer exception.

    I have implemented the bean, created the adapter and everything else which is described in this tutorial. Cannot figure out why the ListView is null. Here is my syntax of the implementation

    theMainView = (ListView) getActivity().findViewById(R.id.list);
    Here I am usig getActivity() to get the application’s activity as it is implemented in a listfragment.

    Any ideas as to what I am doing wrong.

    • Noname

      same problem. did you figured out how to solve it? :)

      • Noname

        solved it. forgot to initiate the arraylist ;)

  • Shweta

    Thank you very much…made my day…

  • Seshat

    Hi!!!! Firstable thank you very much!!! This tutorial helped me a lot! Now I have some questions… What should I do to start a different activity when I click on the image? I mean, every time I click on any item from the list it shows a new layout but I want to do something different when image is clicked. Thanks in advance.

    • http://theopentutorials.com Nithya Vasudevan

      In your custom adapter class, you can try this code inside getView() method

      holder.imageView.setOnClickListener(new OnClickListener() {			
      	@Override
              public void onClick(View v) {
      		Toast.makeText(context, "Clicked on image", Toast.LENGTH_LONG).show();
      	}
      });

      Or you can also have a separate listview for image and separate listview for text.

      <LinearLayout ... Orientation="horizontal">
      <ListView /> <!-- For ImageView -->
      <ListView /> <!-- For TextView -->
      </LinearLayout>
  • Simon

    Great tutorial!

  • bhaskar

    nice tutorial

  • xx

    Thanks!! It helped me a great deal..

  • Georg

    Thank you. I am understand custom array adapter after reading this post only.

  • derrick

    thanks for your tutorial. It was enlightening for a newbie like me, now i have a few question, was wondering how am i able to pass the image in the list view into another activity where it has a imageview and set that activity’s imageview to be the same as the icon?

    cheers!

    • http://theopentutorials.com Nithya Vasudevan

      Read this post to achieve this.

  • Nesma

    Thanks for the amazing tutorial it helped me alot , could you please tell me how to pass the selected items from this listview (don’t want to use check box) to another activity (so they they can also appear in alist and calculate their price in the second activity and get the total )
    (note : i added price )

  • Nerf Edlmen

    Thank you for the nice and detailed description on Android Listview really hepled me alot for other there one more useful video i found on youtube LINK: Android Listview With Images
    hope you’ll find it useful.

  • Nerf Edlmen

    follow the link to goto the video https://www.youtube.com/watch?v=0zQCv0Xb3pk

  • Linea

    Hi, can I ask you something that is not covered in this tutorial?
    What should do if I want to use search view to filter the result?
    can I simply use the code below for ArrayAdapter with both text and image?
    public boolean onQueryTextChange(String newText)
    {

    mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;

    mAdapter.getFilter().filter(mCurFilter);
    return true;
    }
    Thank you !

  • http://www.facebook.com/JogiAsadMirwahi Asad Ali Jogi

    Very Nice tutorial with all steps defined . I am lovi’n it.
    thanks Nithya

  • http://www.facebook.com/JogiAsadMirwahi Asad Ali Jogi

    I have some problem in Calling Listview using customadapter , in the list item after toast I want to calll another listview activity using same code of custom adapter , but it doesn’t loads.

    same above activity of listview as You Nithya have given I have same code first activity shows but after toasting at item of first activity of custom listView I want to call same type another Custom listView activity.
    kindly help

  • Sajal Das

    Thanks. I searched for more than a week for setting source to the imageview in a custom list. This helped me do it. Thanks again :)

  • http://androidtrainningcenter.blogspot.com Tech Trainner

    Very nice example. Best thing about this example is, simple explanation. I am also a blogger write on android. I am fan of your blogs.

  • NDroid

    What is the role of the class “ViewHolder” in this example?

  • PavanKumar

    thank you very much your custom listview example is excellent.it is easy to understand

  • Karthik

    11-16 14:03:01.65: E/AndroidRuntime(4774): FATAL EXCEPTION: main
    11-16 14:03:01.685: E/AndroidRuntime(4774): java.lang.NullPointerException
    11-16 14:03:01.685: E/AndroidRuntime(4774): at com.customlist.CustomListAdapter.getView(CustomListAdapter.java:43)
    Hi..
    I’m a newbie..i am getting this kind of error..dont know how to get it solved..plz do help me out.Thanks

    • Guest

      Thanks

    • anuj

      hey karthik check your code near these line …your overridding your elements change your row_item element ids..and edit them in given lines…:)
      holder.txtTitle = (TextView) convertView.findViewById(R.id.title);
      holder.imageView = (ImageView) convertView.findViewById(R.id.icon);

  • Ravindra Chothe

    Excellent Turotial….I have one question if i want to show Images using url(JSon Response) then how to show?

  • Naveen kant Mishra

    nice tutorial simple small and nice

  • Vlade

    OutOfMemoryError. I get this error… what should I do?

  • Vlade

    OutOfMemoryError… What should I do? Please help.. I am beginner in android..

  • Dev

    i want to display image with text in listview in that content should be load from mysql database,so please help me to solve this……

  • Pingback: Usefull links | inshaf

  • Muhammad Daniyal Anwar

    Hi, how to open any activity on click on any child item?

  • http://www.androidinterview.com/ nilesh kumar
  • rahulmandaliya

    Hello, you provide best tutorial ever i seen in blogs.
    I have question about searching…
    How to search data in custom list view ???