Android: ListView Example with Custom Adapter


Update

I am now working with android api version 16, and come to know android team suggested to use LoaderManager for loading listview.
but loader manager is available from api version 11. so they have published a support version for lower api.
my point is, though the code example below is working fine now but you should get used to loadermanager soon.
you can find an example here. i hope it may help

main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent" >
    <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Hello World, MyActivity" />

    <ListView android:id="@+id/list_data"
              android:layout_height="match_parent"
              android:layout_width="match_parent" />
</LinearLayout>

res/layout/single_list_item.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:id="@+id/tv_string_data"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:text="Sample Data"
              android:textSize="15sp"
              android:paddingBottom="5dp" />


    <Button android:id="@+id/btn_number_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button Text"
            android:paddingBottom="5dp" />

    <TextView android:id="@+id/tv_double_data"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:text="Sample Data 2"
              android:textSize="15sp"
              android:paddingBottom="5dp" />

</LinearLayout>

CustomAdapter.java

package com.example;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

/**
 * Created with IntelliJ IDEA.
 * User: Shahab
 * Date: 8/22/12
 * Time: 11:37 AM
 * To change this template use File | Settings | File Templates.
 */
public class CustomAdapter extends BaseAdapter {

    private static final String TAG = CustomAdapter.class.getSimpleName();
    ArrayList<DataModel> listArray;

    public CustomAdapter() {
        listArray = new ArrayList<DataModel>(5);
        listArray.add(new DataModel("name1", 5, 1.8, "Java"));
        listArray.add(new DataModel("name2", 10, 2.8, "Python"));
        listArray.add(new DataModel("name3", 15, 3.8, "Django"));
        listArray.add(new DataModel("name4", 20, 4.8, "Groovy"));
        listArray.add(new DataModel("name5", 25, 5.8, "Maven"));
    }

    @Override
    public int getCount() {
        return listArray.size();    // total number of elements in the list
    }

    @Override
    public Object getItem(int i) {
        return listArray.get(i);    // single item in the list
    }

    @Override
    public long getItemId(int i) {
        return i;                   // index number
    }

    @Override
    public View getView(int index, View view, final ViewGroup parent) {

        if (view == null) {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            view = inflater.inflate(R.layout.single_list_item, parent, false);
        }

        final DataModel dataModel = listArray.get(index);

        TextView textView = (TextView) view.findViewById(R.id.tv_string_data);
        textView.setText(dataModel.getName());

        Button button = (Button) view.findViewById(R.id.btn_number_data);
        button.setText("" + dataModel.getAnInt());

        textView = (TextView) view.findViewById(R.id.tv_double_data);
        textView.setText("" + dataModel.getaDouble());

        // button click listener
        // this chunk of code will run, if user click the button
        // because, we set the click listener on the button only

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "string: " + dataModel.getName());
                Log.d(TAG, "int: " + dataModel.getAnInt());
                Log.d(TAG, "double: " + dataModel.getaDouble());
                Log.d(TAG, "otherData: " + dataModel.getOtherData());

                Toast.makeText(parent.getContext(), "button clicked: " + dataModel.getAnInt(), Toast.LENGTH_SHORT).show();
            }
        });


        // if you commented out the above chunk of code and
        // activate this chunk of code
        // then if user click on any view inside the list view (except button)
        // this chunk of code will execute
        // because we set the click listener on the whole view


        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "string: " + dataModel.getName());
                Log.d(TAG, "int: " + dataModel.getAnInt());
                Log.d(TAG, "double: " + dataModel.getaDouble());
                Log.d(TAG, "otherData: " + dataModel.getOtherData());

                Toast.makeText(parent.getContext(), "view clicked: " + dataModel.getOtherData(), Toast.LENGTH_SHORT).show();
            }
        });

        return view;
    }
}

DataModel.java



package com.example;

/**
 * Created with IntelliJ IDEA.
 * User: Shahab
 * Date: 8/22/12
 * Time: 11:38 AM
 * To change this template use File | Settings | File Templates.
 */
public class DataModel {
    private String name;
    private int anInt;
    private double aDouble;
    private String OtherData;

    public DataModel(String name, int anInt, double aDouble, String otherData) {
        this.name = name;
        this.anInt = anInt;
        this.aDouble = aDouble;
        OtherData = otherData;
    }


    public String getName() {
        return name;
    }

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

    public int getAnInt() {
        return anInt;
    }

    public void setAnInt(int anInt) {
        this.anInt = anInt;
    }

    public double getaDouble() {
        return aDouble;
    }

    public void setaDouble(double aDouble) {
        this.aDouble = aDouble;
    }

    public String getOtherData() {
        return OtherData;
    }

    public void setOtherData(String otherData) {
        OtherData = otherData;
    }
}

MyActivity.java



package com.example;

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

public class MyActivity extends Activity {

    private static final String TAG = MyActivity.class.getSimpleName();

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

        ListView listView = (ListView) findViewById(R.id.list_data);

        CustomAdapter customAdapter = new CustomAdapter();

        listView.setAdapter(customAdapter);

        // we have added a button on our list view
        // for that reason, list view on item click wont get the event
        // we need to implement click listener in custom adapter
        // this method will work if we do not add button on our list view

//        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
//            @Override
//            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//
//                DataModel dataModel = (DataModel) adapterView.getItemAtPosition(i);
//
//                Log.d(TAG, "string: " + dataModel.getName());
//                Log.d(TAG, "int: " + dataModel.getAnInt());
//                Log.d(TAG, "double: " + dataModel.getaDouble());
//                Log.d(TAG, "otherData: " + dataModel.getOtherData());
//
//                Toast.makeText(MyActivity.this, "Item Clicked: " + i, Toast.LENGTH_SHORT).show();
//            }
//        });
    }
}

AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example"
          android:versionCode="1"
          android:versionName="1.0">
    <uses-sdk android:minSdkVersion="16"/>
    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
        <activity android:name="MyActivity"
                  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>


8 thoughts on “Android: ListView Example with Custom Adapter

  1. How to handle the row to be clickable as well as the button inside the row to be clicked? Thhat means both needs to be clickable.

  2. Smooth man, just smooth. I liked the handling of clicks right inside the getView()
    This was the most straightforward example I came across.

  3. Hello Bro,

    i need your help,

    in my case,
    i have two ListView in one Activity with Custom Adapter
    ListView one = List Data
    ListView two = Display data

    the problem is:
    how to Load data to ListView two
    when button on row ListView one Clicked

    Thank You

  4. How can i use intent in this button?

    button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
    Toast.makeText(parent.getContext(), “button clicked: ” + dataModel.getAnInt(),
    Toast.LENGTH_SHORT).show();
    // use intent here
    }
    });
    thanks in advance

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.