Android ListView with Adapter Example
How android ListView with adapter works is not so clear to me until I read this awesome examples and article of Lucas Rocha: Performance Tips for Android’s ListView.
Today I’m going to show you the code I use whenever I wanted the user to select an “item” in an AlertDialog with ListView. If you are looking for an example AlertDialog with simple ListView (without an adapter), here’s a blog post I made: Android AlertDialog with ListView.
A ListView item here contains a text (item name) and an ID (item ID), so whenever the user selects an item in the pop up, you’ll be able to get the text and ID of that selected item. This is very useful if the items are from a database – records with IDs and names. The tags (item IDs) were set using the TextView’s setTag() method.
Video Demo
Here’s the final output of our code for today. Name and ID were fetched and show via toast.
Code Download
You can download the code we used here: ListViewPopUpWithAdapter.zip
Let’s Code!
We only need 6 files to run this sample code successfully.
1. activity_main.xml – our main layout. Our trigger to show the ListView is a button.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <Button android:id="@+id/buttonShowPopUp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Show AlertDialog with ListView" /> </RelativeLayout>
2. MainActivity.java – will show the main layout, a button at the center of the screen. Clicking that button will show our awesome ListView.
package com.example.listviewpopupwithadapter; import android.os.Bundle; import android.view.View; import android.widget.ListView; import android.app.Activity; import android.app.AlertDialog; public class MainActivity extends Activity { AlertDialog alertDialogStores; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // a button to show the pop up with a list view View.OnClickListener handler = new View.OnClickListener(){ public void onClick(View v) { switch (v.getId()) { case R.id.buttonShowPopUp: showPopUp(); break; } } }; findViewById(R.id.buttonShowPopUp).setOnClickListener(handler); } public void showPopUp(){ // add your items, this can be done programatically // your items can be from a database ObjectItem[] ObjectItemData = new ObjectItem[20]; ObjectItemData[0] = new ObjectItem(91, "Mercury"); ObjectItemData[1] = new ObjectItem(92, "Watson"); ObjectItemData[2] = new ObjectItem(93, "Nissan"); ObjectItemData[3] = new ObjectItem(94, "Puregold"); ObjectItemData[4] = new ObjectItem(95, "SM"); ObjectItemData[5] = new ObjectItem(96, "7 Eleven"); ObjectItemData[6] = new ObjectItem(97, "Ministop"); ObjectItemData[7] = new ObjectItem(98, "Fat Chicken"); ObjectItemData[8] = new ObjectItem(99, "Master Siomai"); ObjectItemData[9] = new ObjectItem(100, "Mang Inasal"); ObjectItemData[10] = new ObjectItem(101, "Mercury 2"); ObjectItemData[11] = new ObjectItem(102, "Watson 2"); ObjectItemData[12] = new ObjectItem(103, "Nissan 2"); ObjectItemData[13] = new ObjectItem(104, "Puregold 2"); ObjectItemData[14] = new ObjectItem(105, "SM 2"); ObjectItemData[15] = new ObjectItem(106, "7 Eleven 2"); ObjectItemData[16] = new ObjectItem(107, "Ministop 2"); ObjectItemData[17] = new ObjectItem(108, "Fat Chicken 2"); ObjectItemData[18] = new ObjectItem(109, "Master Siomai 2"); ObjectItemData[19] = new ObjectItem(110, "Mang Inasal 2"); // our adapter instance ArrayAdapterItem adapter = new ArrayAdapterItem(this, R.layout.list_view_row_item, ObjectItemData); // create a new ListView, set the adapter and item click listener ListView listViewItems = new ListView(this); listViewItems.setAdapter(adapter); listViewItems.setOnItemClickListener(new OnItemClickListenerListViewItem()); // put the ListView in the pop up alertDialogStores = new AlertDialog.Builder(MainActivity.this) .setView(listViewItems) .setTitle("Stores") .show(); } }
3. ObjectItem.java – each item in the list is considered as an object with name and ID.
package com.example.listviewpopupwithadapter; //another class to handle item's id and name public class ObjectItem { public int itemId; public String itemName; // constructor public ObjectItem(int itemId, String itemName) { this.itemId = itemId; this.itemName = itemName; } }
4. ArrayAdapterItem.java – where our ListView performance depends.
package com.example.listviewpopupwithadapter; 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.TextView; // here's our beautiful adapter public class ArrayAdapterItem extends ArrayAdapter<ObjectItem> { Context mContext; int layoutResourceId; ObjectItem data[] = null; public ArrayAdapterItem(Context mContext, int layoutResourceId, ObjectItem[] data) { super(mContext, layoutResourceId, data); this.layoutResourceId = layoutResourceId; this.mContext = mContext; this.data = data; } @Override public View getView(int position, View convertView, ViewGroup parent) { /* * The convertView argument is essentially a "ScrapView" as described is Lucas post * http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/ * It will have a non-null value when ListView is asking you recycle the row layout. * So, when convertView is not null, you should simply update its contents instead of inflating a new row layout. */ if(convertView==null){ // inflate the layout LayoutInflater inflater = ((Activity) mContext).getLayoutInflater(); convertView = inflater.inflate(layoutResourceId, parent, false); } // object item based on the position ObjectItem objectItem = data[position]; // get the TextView and then set the text (item name) and tag (item ID) values TextView textViewItem = (TextView) convertView.findViewById(R.id.textViewItem); textViewItem.setText(objectItem.itemName); textViewItem.setTag(objectItem.itemId); return convertView; } }
5. OnItemClickListenerListViewItem.java – answers what will happen if the user clicks an item in the list?
package com.example.listviewpopupwithadapter; import android.content.Context; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.TextView; import android.widget.Toast; /* * Here you can control what to do next when the user selects an item */ public class OnItemClickListenerListViewItem implements OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Context context = view.getContext(); TextView textViewItem = ((TextView) view.findViewById(R.id.textViewItem)); // get the clicked item name String listItemText = textViewItem.getText().toString(); // get the clicked item ID String listItemId = textViewItem.getTag().toString(); // just toast it Toast.makeText(context, "Item: " + listItemText + ", Item ID: " + listItemId, Toast.LENGTH_SHORT).show(); ((MainActivity) context).alertDialogStores.cancel(); } }
6. list_view_row_item.xml – the layout of each item in the list. You can modify this if you want to have an image or subtitle for each item of your ListView.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp" > <TextView android:id="@+id/textViewItem" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:text="Item name here..." android:textSize="15dp" /> </RelativeLayout>
Love that you’re excited and publishing tutorials. JCG gets a pretty wide distribution. Can I suggest that you implement the ViewHolder pattern in your adapter as it’s an accepted pattern that can significantly increase performance. In your tutorial? Probably not, but people will use your solution as gospel ;) You’ll notice that my friends and I have further extended the ViewHolder pattern with a constructor that accepts a View. We did this to encourage the next person in your code to do it right. We’re calling this “Offensive Programming.” Cheers.
https://github.com/androidfu/CodeExamples/blob/master/ContactGroupListExample/src/com/androidfu/contactgrouplistexample/ContactGroupListExampleActivity.java
Wonderful comment, thanks Bill. Sure, I will include the ViewHolder pattern but in another post. :) I also think that the Android ListView can also be difficult to understand at times as said in the official dev blog: http://android-developers.blogspot.com/2009/01/why-is-my-list-black-android.html You’ll notice that I know some of your friends. So I suggest that it is better to understand something like my post above first, and then the performance optimization will come next. I’ve written about the ViewHolder pattern here, please let us know if you can add more valuable points: http://www.codeofaninja.com/2013/09/android-viewholder-pattern-example.html By the way, why does your ViewHolder pattern has a… Read more »
Because he likes being able to set those properties directly
I didn’t respond previously because if you read more than the Twitter version of my comment you’d see the question was already answered ;)
“You’ll notice that my friends and I have further extended the ViewHolder pattern with a constructor that accepts a View. We did this to encourage the next person in your code to do it right. We’re calling this “Offensive Programming.” Cheers.”
Hi,Mike Dalisay
i have a trouble and i hope you could help me.
This is my code:
ArrayListApdapter arr=new ArrayListApdapter(MainActivity.this, R.layout.list_custom, ObjectItemData);
ListView list=(ListView)findViewById(R.id.listView1);
list.setAdapter(arr);
i want to show my data into this listView1 but it “Unfortunately,listView1 has stopped”.You can show me how the way to do that.Thanks u
Hey you, i think
ArrayListApdapter arr=new ArrayListApdapter(MainActivity.this, R.layout.list_custom, ObjectItemData);\
you dont have type of ArrayAdapter
Just a heads up- the code download link isn’t working for me. But still, this was a great introductory tutorial. Thanks.
Good one……………Also see more @……..http://androidtutorialsrkt.blogspot.in/
Hi,Mike Dalisay,
I made new project and paste your code in the files as you mentioned the names
Their is only 1 error in the following line:
findViewById(R.id.buttonShowPopUp).setOnClickListener(handler);
Error: handler cannot be resolved to a variable
I am confused what to do now, I have tried to many things to resolve the issue, but didn’t get success :(
Hope i will get your reply soon
dude, im stuck on step 2.
using android studio 0.8.0 as IDE, cannot resolve symbol ‘ObjectItem’, ‘ArrayAdapterItem’, ‘list_view_row_item’ and ‘OnItemClickListenerListViewItem’.
what should i do?
Nice code and good explanations.
Thanks!
Hai,
Thanks for investing your time for writing this think different tutotial.. I feel u wuld have write your ideas in words before writing codes. More explanation will helps to understand more easily. I dont undersand two things . they are int layoutResourceId in arraryadapter class and other thing is listview without list widget in xml.
Will be happy if u explain.
convertView = inflater.inflate(layoutResourceId, parent, false);
Variable parent from where it is coming.
Where is declaration or definition of it….
Sorry, it is ViewGroup…
Thanks for tutorial…
Hello there! I wanted to say this is a pretty good tutorial, really really nice and functional.
I just have an issue, when I’m on the getView method of the Adapter class. I’m getting a ClassCastException in thie line of code: if(convertView == null) { and i honestly don’t know why…
Can you guys please help me?
Thanks in advance
In arrayItemAdapter.java file formal variables and instance variables have same identifier For example look at the following variables mContext,layoutResourceId,data They are the variables of the class arrayAdapterItem but in the constructor the instance parameters also have the same name. They are different variables right? I mean the mContext used in the contructor is different for the variable of the class right? 14 Context mContext; 15 int layoutResourceId; 16 ObjectItem data[] = null; 17 18 public ArrayAdapterItem(Context mContext, int layoutResourceId, ObjectItem[] data) { 19 20 super(mContext, layoutResourceId, data); 21 22 this.layoutResourceId = layoutResourceId; 23 this.mContext = mContext; 24 this.data = data;… Read more »
Nevermind.Couldn’t have been more stupid.
Should never have posted at the first glance
object Item ObjectItemData[0] = new ObjectItem(91, “Mercury”);
when “Mercury”is clicked the move to another ………Property of Mercury
how is to make?
This condition