This tutorial will show how to prepare ListView with custom items and buttons (with click handlers) like this:

Android ListView with custom items
Source Code
The source code for this tutorial is in this post. You can download it and use as You like.
1. Create single list item layout
Item consists of three views: name, value (EtitTexts) and delete (Button). Its atom_pay_list_item.xml layout is as follows:
<?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="horizontal" >
<EditText
android:id="@+id/atomPay_name"
android:layout_width="0sp"
android:layout_height="fill_parent"
android:layout_weight="2"
android:gravity="center_vertical"
android:hint="@string/EnterPays_atomPay_nameHint"
android:textAppearance="?android:attr/textAppearanceSmall" />
<EditText
android:id="@+id/atomPay_value"
android:layout_width="0sp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:inputType="numberDecimal"
android:text="@string/EnterPays_TextView_ZeroValue"
android:textAppearance="?android:attr/textAppearanceSmall" />
<ImageButton
android:id="@+id/atomPay_removePay"
android:layout_width="@dimen/width_button"
android:layout_height="fill_parent"
android:contentDescription="@string/emptyText"
android:onClick="removeAtomPayOnClickHandler"
android:src="@android:drawable/ic_menu_delete" />
</LinearLayout>
Notice, that the button has onClick handler defined in xml layout file. This is because I want to refer its action to specific list item, so handler will be implemented in Activity file and each button will know to which list item it belongs. Later I will show how to do it in detail.
2. Create list item adapter
This is java class that is a controller for atom_pay_list_item.xml. It keeps references for all of its views and puts these references in tags and extends ArrayAdapter. My adapter looks as follows:
public class AtomPayListAdapter extends ArrayAdapter<AtomPayment> {
private List<AtomPayment> items;
private int layoutResourceId;
private Context context;
public AtomPayListAdapter(Context context, int layoutResourceId, List<AtomPayment> items) {
super(context, layoutResourceId, items);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.items = items;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
AtomPaymentHolder holder = null;
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new AtomPaymentHolder();
holder.atomPayment = items.get(position);
holder.removePaymentButton = (ImageButton)row.findViewById(R.id.atomPay_removePay);
holder.removePaymentButton.setTag(holder.atomPayment);
holder.name = (TextView)row.findViewById(R.id.atomPay_name);
holder.value = (TextView)row.findViewById(R.id.atomPay_value);
row.setTag(holder);
setupItem(holder);
return row;
}
private void setupItem(AtomPaymentHolder holder) {
holder.name.setText(holder.atomPayment.getName());
holder.value.setText(String.valueOf(holder.atomPayment.getValue()));
}
public static class AtomPaymentHolder {
AtomPayment atomPayment;
TextView name;
TextView value;
ImageButton removePaymentButton;
}
}
Here I display list of AtomPayment class items. There are three most important elements here:
- AtomPayListAdapter constructor: sets some private fields and calls superclass constructor. It also gets the List of AtomPayment objects. Its implementation is obligatory.
- AtomPaymentHolder: static class that holds references to all views that I have to set in this list item. I also keep the AtomPayment object that references to this particular item in list. I set it as tag for ImageButton, that will help me to find the AtomPayment item on list, that user wanted to remove
- Overriden getView method: called by superclass. Its goal is to return the single List row. I create its fields and setup their values and store them in static holder. Holder then is put in row’s tag element. Note that there is an performance issue: row is being recreated each time it is displayed. I used to add some flag in holder like isCreated, and set it to true after row was already created. then you can add if statement and read tag’s holder instead of creating it from scratch.
My AtomPayment.java is quite simple as for now and it looks a bit like BasicNameValuePair:
public class AtomPayment implements Serializable {
private String name = "";
private double value = 0;
public AtomPayment(String name, double value) {
this.setName(name);
this.setValue(value);
}
...
}
Of course there are additionally getters and setters for each private field.
3. add ListView in your activity layout xml file
In the simpliest form, it is enough to add this view to activity layout:
<ListView
android:id="@+id/EnterPays_atomPaysList"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</ListView>
4. Set up adapter to this list view in Activity Java code
In order to display items in ListView you need to set up its adapter and map it to some other ArrayList of AtomPayment objects (as I am extending an Array adapter here). Here is code that is responsible for binding adapter to editPersonData.getAtomPayments() ArrayList:
AtomPayListAdapter adapter = new AtomPayListAdapter(AddNewPerson.this, R.layout.atom_pay_list_item, editPersonData.getAtomPayments());
ListView atomPaysListView = (ListView)findViewById(R.id.EnterPays_atomPaysList);
atomPaysListView.setAdapter(adapter);
5. Adding / removing items to ListView (and its adapter)
Adapter is handled just like any other ArrayList, so adding new element to it is as simple as:
AtomPayment testAtomPayment = new AtomPayment("Test", 13);
adapter.add(testAtomPayment);
adapter.remove(testAtomPayment);
6. Handle Remove Payment button click event
In an activity’s code, where ListView is displayed, add public method that will handle remove button click action. The method name has to be exactly the same as it was in atom_pay_list_item.xml:
android:onClick="removeAtomPayOnClickHandler"
The method body is as follows:
public void removeAtomPayOnClickHandler(View v) {
AtomPayment itemToRemove = (AtomPayment)v.getTag();
adapter.remove(itemToRemove);
}
The AtomPayment object was stored in ImageButton’s Tag element. Now it is enough to read it from Tag, and remove this item from the adapter.
7. Incorporate remove confirmation dialog window
Probably you need also make sure that user intentionally pressed the remove button by asking him additional question in confirmation dialog like this one:

Confirmation dialog sample
Please go to my post that contains tutorial how to show and handle confirmation dialog to find out how to do it.
Source Code
The source code for this tutorial is in this post. You can download it and use as You like.
Like this:
Like Loading...