This Android Listview tutorial describes how to use Android ListView with multiple rows. Usually, we are used to a ListView with all rows having the same layout. This tutorial describes how to handle Android ListView with multiple row layout or in other words, rows that have different UI widget inside.
You may already know how to create and handle an Android ListView, if not give a look at this post before reading this post.
Just to remember briefly the main concepts, to create and handle an Android ListView it is necessary:
At the end of this post, we will create an Android app that looks like the picture shown below:
In this app, we show a Contact list that has two different layouts one that uses an image and another one without an image. Even if the example is quite simple, it is enough to understand how to use several ListView methods to get this result.
How to implement Android Listview with multiple row layout
Usually, when we want to customize the ListView data we use a custom adapter. We know Android provides some basic ready-to-use adapter (i.e ArrayAdapter, SimpleAdapter and so on) . We know, already, that all these adapters have in a common a father class known as BaseAdapter.
The BaseAdapter has two methods that are very useful if we want to have multiple row layouts:
- public int getItemViewType(int position)
- public int getViewTypeCount()
The method getViewTypeCount “returns the number of types of Views that will be created by getView(int, View, ViewGroup)“.
In other words, this method returns how many different layouts we have in our ListView. The getItemViewType returns the view type of the current row, if you look at the method signature we have the position as a parameter. One thing we should notice is that this method must return an integer value between 0 and the getViewTypeCount() – 1.
So if we want to have multiple row layout, we have to override these methods and returns the right values.
How to implement a multiple row layout in ListView
As first thing to implement an app with Android ListView with multiple rows, we have to create a custom adapter, that we call ContactAdapter:
[java]public class ContactAdapter extends BaseAdapter {…
}[/java]
and to have two different layouts, we override:
[java]@Overridepublic int getViewTypeCount() {
return 2;
}
[/java]
and then we have to implement the logic to select the type of layout to assign to the row according to the position value:
[java]@Overridepublic int getItemViewType(int position) {
return (contactList.get(position).getContactType() == ContactType.CONTACT_WITH_IMAGE) ? 0 : 1;
}[/java]
In this method, we use getContactType to know which layout to use, as you can see we return 0 or 1.
Now we have to implement two different layouts: they are very similar:
[xml]<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:id="@+id/img"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/name"
android:layout_toRightOf="@id/img"
android:layout_marginTop="2dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/surname"
android:layout_toRightOf="@id/name"
android:layout_marginLeft="4dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/email"
android:layout_below="@id/name"
android:layout_alignStart="@id/name"
android:layout_marginTop="4dp"/>
</RelativeLayout>[/xml]
and the other one without the image is:
[xml]>RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/name"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/surname"
android:layout_toRightOf="@id/name"
android:layout_marginLeft="4dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/email"
android:layout_below="@id/name"
android:layout_alignStart="@id/name"
android:layout_marginTop="4dp"/>
</RelativeLayout>[/xml]
Now we have simply to override, in our custom adapter, the getView method:
[java]@Overridepublic View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
int type = getItemViewType(position);
if (v == null) {
// Inflate the layout according to the view type
LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (type == 0) {
// Inflate the layout with image
v = inflater.inflate(R.layout.image_contact_layout, parent, false);
}
else {
v = inflater.inflate(R.layout.simple_contact_layout, parent, false);
}
}
//
Contact c = contactList.get(position);
TextView surname = (TextView) v.findViewById(R.id.surname);
TextView name = (TextView) v.findViewById(R.id.name);
TextView email = (TextView) v.findViewById(R.id.email);
if (type == 0) {
ImageView img = (ImageView) v.findViewById(R.id.img);
img.setImageResource(c.imageId);
}
surname.setText(c.surname);
name.setText(c.name);
email.setText(c.email);
return v;
}[/java]
Assembling the app
Now we have our custom adapter is very easy to use it and bind it to the ListView. In the main activity that holds the ListView:
[java]@Overrideprotected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
ContactAdapter ca = new ContactAdapter(createContact(20), this);
ListView lv = (ListView) findViewById(R.id.contact_list);
lv.setAdapter(ca);
}
[/java]
In this post, we created an Android app using ListView that holds different row layouts.
Thanks for the example!
Thanks for the example!
Thanks for the example
Thanks for the example
hey how about int resource at constructor? when we had 2 layout? can you share full code the custom adapter?
hey how about int resource at constructor? when we had 2 layout? can you share full code the custom adapter?
how to add onlicklistener on these things
how to add onlicklistener on these things
Can you send the source code?
Can you send the source code?
source code????
Each time is called findViewbyId() ….
Use ViewHolder for optimization.
Each time is called findViewbyId() ….
nice tutorial….
how to add more than 2 different layouts to list view?
here you go http://androidprogramsforyou.blogspot.in/2015/07/adding-more-than-two-different-layouts.html
Appreciate for your tutorial, I create another Adapter extends SimpleCursorAdapter and only override getView and getItemViewType methods. It works fine now. Thank you again!
By the way, I do think this way is better than using ViewBinder.
A Francé, ma ‘sti codici?
Please send full Code
Are you not recycling views? What does this do when the lists are large?
Thanks for tthe tutorial, in my json the type is radio or checkbox but the problem is they differ in count for each item to item in the listview
What if I want to set different layouts in position pairs, and other in position odd?
I don’t get it, isn’t supposed to do this with an ArrayList??
Very simple and useful, thank you.
pls send the source code for me? thank!
email: [email protected]
Thanks, Excellent example…
this is a nice example but the code isn’t complete.
please send me source code,[email protected]
can you send me the source code [email protected]
can u plz send me the send me the source code
can you send me the source code [email protected]
source code please [email protected]
Magnifik can i get code complete.thank very lot