Custom ListView with image and text using with ArrayAdapter

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.

Leave a Comment