This tutorial will show how to prepare ListView with custom items and buttons (with click handlers) like this:
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:
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.
Did I help you?
I manage this blog and share my knowledge for free sacrificing my time. If you appreciate it and find this information helpful, please consider making a donation in order to keep this page alive and improve quality
Thank You!
Hi,
congratulations very good tutorial.
Could you add such a confirmation dialog for deletion? It should be simple, but I can not find how to do it.
Thanks again for the tutorial.
regards
I posted confirmation dialog tutorial for you, and updated ListView tutorial with a new step (7) as well:
https://looksok.wordpress.com/2012/11/07/android-remove-confirmation-dialog-window/
I’m glad you liked this one! Take care and happy coding!
Instead of edittext may i know how to change the edittext to a spinner inside your open source coding?
Just declare spinner in list items’ xml instead of edit text
can you post the source code in this link also
You mean custom ListView or remove confirmation dialog source code? Both instructions are pretty well described, so it should be easy to develop it by yourself.
My source code is currently a part of big project, so it would be hard for me to post it.
DO you have the code to download this
Not really because this is a part of bigger project, so there is big overhead in project.
I suppose that this is described precisely enough. But let me know if you still can’t handle it and realy need source code.
Hey the line “adapter.remove(itemToRemove)” Throws —> java.Lang.IllegalStateException caused by java.Lang.UnsupportedOperationException
?????? Please help!
can you show me somehow your source code (view it on some repository) or full stacktrace?
Actually I have loaded a List(using arrayAdapter) with data from Database… Now I want to delete a row… But when I use your above code it Force closes
:(
It is hard to say anything without logcat
As in this example, you can implement the functions onSaveInstanceState and onRestoreInstanceState?
As in this example, you can implement the functions onSaveInstanceState and onRestoreInstanceState?
I am not sure if I correctly get what you mean. Could you please clarify your question?
I apologize for the stupid question. I want to know about the function onSaveInstanceState and onRestoreInstanceState
My code wasn’t tested with it – This is meant to be simple tutorial on listView, not on saving and restoring states.
Usually you restore your state in onCreate(). onRestoreInstanceState() is called after onStart()
You can use the put methods to store values in onSaveInstanceState():
protected void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
icicle.putLong(“param”, value);
}
the editPersonData.getAtomPayments() contains a List?
Yes – it returns an ArrayList with AtomPayment items
Sir Can you give me editPersonData.getAtomPayments()
code?
You don’t need it. Just abstract from it
Can you please merge the codes in their own respective classes and xml? I’m having a hard time to understand, Thanks!
OK – I’ll write source code for it and share it.
Unfortunately I won’t be able to do it until next saturday (27.4.2013)… Please stay tuned!
I’ve merged all the codes and written source code based on this tutorial, as promised.
Please check this post:
https://looksok.wordpress.com/2013/04/27/source-code-android-custom-listview/
hello, your tutorial is really good and simple so understan for a newbie like myself :D. But i have an issue, i made buttons like you did in the row of the listview theses buttons have to activate a checkbox each, and it’s work but i can’t save the states of thoses checkbox so i can’t be sure if every row has their own checkboxes when i click on the buttons .
Add OnCheckedChanged listener for checkbox in adapter and in that listener you will have to persist checkbox state in your model (atomPayment item in my case)
See my sorce code, how I persist editText’s value
hello again,
the listview you made, how can you save the listview when i.e i hit the back button and then come back again on the activity, all the items i create dissapeared .
You need to implement some data storage for it and persist all the list items (ArrayList) in it. For example you can use shared preferences. And after that, when you create activity, you have to load this data back
Search for post regarding shared preferences tutorial on my blog
hello!
very nice tutorial!:) i like it.
but i have 1 problem: your second edittext is numberDecimal. i changed it, but still appers as “0.0”.
well my problem is: i need it to be only “1”, and just to be hint, so if i click, user can enter a value without erasing the “1” value.
i can’t figure it out, so pls help :)
thanks in advance
probably the default value is set to “0.0”. please check it in list item’s xml file. change it to 1.
As far as I remember – the default value (0.0) is taken from strings.xml. check there
“0.0” is not found in your entire soure.
i changed it to an int value (to be round only) on the insert method
public void onClick(View v) {
int k=1;
adapter.insert(new AtomPayment(“1”, k), 0);
also don’t works
thanks for fast reply
any more ideas?
also changed the numericDecimal in xml to decimal
Change type ‘double’ to ‘int’ in AtomPayment.java for ‘value’ field. Should help :)
hellyeah! had to change some method parameters too, but it’s working:)
BIGBIGTHANKYOU
i’m struggling with a TextView wich sums up the added listitems’ Edittext values.
how should i doit?
can’t figure it out :(
any tips or ideas?
Iterate over each adapter’s list item and sum up each one’s value
help me!!
How will i store all the value of editext present in a listview ?
In shared preferences. Search for another post on my blog how to do it.
If not shared preferences, you can use database our file storage
Actually i mean,
if we put the value in edittext for all the edittext present in the listview
and press submit button ,then i want to send all the value of edittext value to the server for further process….
so i am unable to get the value entered in the edittext.
etitText.getText()
Hey i have added my customlistview in database.
you are right. when i click on that button my view is deleted but not from database. so what to do to delete that as well as from database.
just call your delete method on database in onClick method
Very helpful for me..really great..but how to read the exact values of edit text from this list?? Please help me.
each row / item in an adapter has holder in its tag. Choose item in adapter you want to read, get this holder from this item, find edittext in holder and read its content
Im having problems with the row.settag() and in the method which is fired on the OnClick … v.Gettag() ) is always null.
you place the holder object into the row.setTag();
then you cast the v.gettag() as a AtomPayment. how does it do that when it holds other information i.e. editviews and image button??
say if for every row in the listview i just did row.settag(count++); each row would have a unique number… on the onclick method how would i get that from the View?
by gettag, parsed to the class that you put there. but remember, that you set tag to the whole view, so you need to listen to the view click.
I am not sure whther it is possible to hold pribmitives in tag, while setTag expects object. Maybe it uses autoboxing.
Fire my source code and analyze how does it happen that in my case the object is valid, while your tag is null
Nice tutorial, I was really struggling on how the connection was made from the button in the listview item and using it’s handler in the main event. Thanks for the help.
Great tuto, just what I needed, thanks !
Great, clean and easy to follow.
Thank you
nice tutorial
Nice tutorial! I’d like to sum the numbers inside the EditTexts, but I have no idea how to find out. Any ideas? Thank you so much!
Convert them to double. Java basics
Thank you, worked for me!
Thanks for this post.
I’m really new in Android and Java programming and with your example I was trying to make a simple thing but I could not get there.
I just wanted to let the user press the add button if the 1st row has any vaue.
Could you tell me how to do it?
Hello, congratulations for the tutorial!
I have a question though, how do we listen for changes in the EditText fields? And how to retrieve them?
Thank you in advance!
See onTextChangeListener
Very good Tutorial, I love it.
I still have a problem accessing the object in the ListView.
public void ListView_Selected(View v){
depot.temporary = ((paper)v.getTag());
startActivity(new Intent(getApplicationContext(), DetailView.class));
}
i want to copy the selected object in a temporary object so I can work and display that temporary object.
but the View returns an empty object
In this
The edit text not work properly
When I press on add new item button, new rows are adding above others. How to change it, so new rows will be added bottom of others?
Just reorder your list of items. You can append or prepend items as you need
editPersonData.getAtomPayments()
What should I do about this? I totally dont get it. Please Help.
Hi,
Your Tutorial is awesome, i am new to this listview topic and got really complicated functionality to implement.
i am having some questions regarding this tutorial:
1. how can i get a particular index of listitem if i press delete button.
2. how can i add the 2nd edittext values and get its sum on a textview.
please explain about this…
and my other doubt is inside this link:
please help me out with this one.
https://stackoverflow.com/questions/47728322/recognitionlistener-gives-nullpointerexception-with-viewholder