Android: Custom ListView with Image and Text using BaseAdapter

8 September 2012 By Nithya Vasudevan 51,298 views 12 Comments
47 Flares Twitter 1 Facebook 29 Google+ 17 47 Flares ×

Project Description

  • 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 BaseAdapter.
  • Job of an Adapter:
    • defines how each row is displayed (i.e) the layout for each row. We will define layout for ListView rows 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

styles.xml

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

<resources>
    <style name="AppTheme" parent="android:Theme.Light" />
</resources>

strings.xml

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

<resources>
    <string name="app_name">SimpleImageTextListViewBaseAdapter</string>
    <string name="hello_world">Hello world!</string>
    <string name="menu_settings">Settings</string>
    <string name="title_main_activity">SimpleImageTextList</string>
    <string name="image">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 BaseAdapter class

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

package com.theopentutorials.android.adapters;

import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.theopentutorials.android.activities.R;
import com.theopentutorials.android.beans.RowItem;

public class CustomBaseAdapter extends BaseAdapter {
	Context context;
	List<RowItem> rowItems;
	
	public CustomBaseAdapter(Context context, List<RowItem> items) {
		this.context = context;
		this.rowItems = items;
	}
	
	/*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;
		
		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();
		}
		
		RowItem rowItem = (RowItem) getItem(position);
		
		holder.txtDesc.setText(rowItem.getDesc());
		holder.txtTitle.setText(rowItem.getTitle());
		holder.imageView.setImageResource(rowItem.getImageId());
		
		return convertView;
	}

	@Override
	public int getCount() {		
		return rowItems.size();
	}

	@Override
	public Object getItem(int position) {
		return rowItems.get(position);
	}

	@Override
	public long getItemId(int position) {
		return rowItems.indexOf(getItem(position));
	}
}

Activity class

Create a new class “ImageTextListBaseAdapterActivity” 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.adapters.CustomBaseAdapter;
import com.theopentutorials.android.beans.RowItem;

public class ImageTextListBaseAdapterActivity 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);
		CustomBaseAdapter adapter = new CustomBaseAdapter(this, 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 BaseAdapter and passes the list of RowItems.
  • Sets this adapter in the ListView.

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.theopentutorials.android.activities"
    android:versionCode="1"
    android:versionName="1.0" >

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

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".ImageTextListBaseAdapterActivity"
            android:label="@string/title_main_activity" >
            <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: , , , , , , , , , , , , , ,

  • vafa.sajad

    Hello dear.
    Thanks for tutorial.
    Can you help me with adding a spinner in a row of the above listview?
    I can’t define String for get and set of Spinner.
    Thanks in advance.

  • Pingback: How to list view : Android Community - For Application Development

  • Pingback: Customize ListView using BaseAdabter : Android Community - For Application Development

  • vinod

    Hi pal,
    your article was very useful to me.
    thank you

  • Anat

    Thank you for a great tutorial.

  • Joel

    nice tutorial, but how do we view these apps in alphabetical order by using this code. Any help will be appreciated

  • hum

    Very nice tutorial, thanks a lot for it.

  • Akhil

    Hey thank you for the tutorial. I want to know get image from url and load into listView
    waiting for Replay…..

  • kishore kumar

    thanks for the tutorial. If you have explained the flow its still better to understand fast.

  • Robi kumar Tomer

    gr8 explanation………..also see@ http://androidtutorialsrkt.blogspot.in/

  • jayceed Deyro

    My question would be what if the image is from JSON url?.. how can you load the image to a listview?..

  • Francisco

    Hello!!
    Thanks for the tutorial, but it doesn’t works for me, in CustomBaseAdapter, can’t find the list_item, and it throws me an error. Can you tell me how I fix it?