Creating Custom ListView In Xamarin Android App

Introduction

In this article, we are going to learn about how to create a custom ListView in Xamarin Android app.

Solution

Here are the steps to add tabs in an Android app.

Step 1

Create/ open your Android solution in Visual Studio or Xamarin Studio.

Step 2

Create the ListView inside your AXML file, as shown below.

(File Name: main.axml) 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent">  
  6.     <ListView  
  7.         android:id="@+id/listView"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:fastScrollEnabled="true" />  
  11. </LinearLayout>   

Step 3: Initialize ListView in MainActivity, as shown below.

 (File Name: MainActivity.cs) 

  1. public class MainActivity : Activity  
  2.     {  
  3.         //Intialize ListView  
  4.         ListView myList;  
  5.         protected override void OnCreate(Bundle bundle)  
  6.         {  
  7.             base.OnCreate(bundle);  
  8.   
  9.             // Set our view from the "main" layout resource  
  10.             SetContentView(Resource.Layout.Main);  
  11.   
  12.             myList = FindViewById<ListView>(Resource.Id.listView);  
  13.             
  14.         }  
  15.     }      

Step 4

Now, create the row for the ListView cell to show the details of the user as Name, Image and Department.

(FileName: userRow.axml) 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="horizontal"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:minWidth="25px"  
  7.     android:minHeight="25px"  
  8.     android:paddingBottom="4dp">  
  9.     <ImageView  
  10.         android:id="@+id/photoImageView"  
  11.         android:layout_width="60dp"  
  12.         android:layout_height="60dp"  
  13.         android:layout_alignParentLeft="true"  
  14.         android:layout_centerVertical="true"  
  15.         android:padding="5dp" />  
  16.     <TextView  
  17.         android:id="@+id/nameTextView"  
  18.         android:layout_toRightOf="@id/photoImageView"  
  19.         android:text="Name"  
  20.         android:textAppearance="?android:attr/textAppearanceLarge"  
  21.         android:layout_width="wrap_content"  
  22.         android:layout_height="wrap_content"  
  23.         android:paddingLeft="5dp" />  
  24.     <TextView  
  25.         android:id="@+id/departmentTextView"  
  26.         android:layout_toRightOf="@id/photoImageView"  
  27.         android:layout_below="@id/nameTextView"  
  28.         android:text="Department"  
  29.         android:textAppearance="?android:attr/textAppearanceSmall"  
  30.         android:layout_width="wrap_content"  
  31.         android:layout_height="wrap_content"  
  32.         android:paddingLeft="5dp" />  
  33. </RelativeLayout>   

Step 5

Create User Model, as shown below.

(File Name: User.cs) 

  1. public class User  
  2.     {  
  3.         public string Name { get; set; }  
  4.         public string ImageUrl { get; set; }  
  5.         public string Department { get; set; }  
  6.         public string Details { get; set; }  
  7.   
  8.         public override string ToString()  
  9.         {  
  10.             return Name + " " + Department;  
  11.         }  
  12.     }   

Step 6

To bind the row, we required ListView Adapter, so create a Custom Adapter, as shown below.

 (File Name: MyCustomListAdapter.cs) 

  1. public class MyCustomListAdapter : BaseAdapter<User>  
  2.     {  
  3.         List<User> users;  
  4.   
  5.         public MyCustomListAdapter(List<User> users)  
  6.         {  
  7.             this.users = users;  
  8.         }  
  9.   
  10.         public override User this[int position]  
  11.         {  
  12.             get  
  13.             {  
  14.                 return users[position];  
  15.             }  
  16.         }  
  17.   
  18.         public override int Count  
  19.         {  
  20.             get  
  21.             {  
  22.                  return users.Count;  
  23.             }  
  24.         }  
  25.   
  26.         public override long GetItemId(int position)  
  27.         {  
  28.             return position;  
  29.         }  
  30.   
  31.         public override View GetView(int position, View convertView, ViewGroup parent)  
  32.         {  
  33.             var view = convertView;  
  34.   
  35.             if(view==null)  
  36.             {  
  37.                 view = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.userRow, parent, false);  
  38.   
  39.                 var photo = view.FindViewById<ImageView>(Resource.Id.photoImageView);  
  40.                 var name = view.FindViewById<TextView>(Resource.Id.nameTextView);  
  41.                 var department = view.FindViewById<TextView>(Resource.Id.departmentTextView);  
  42.   
  43.                 view.Tag = new ViewHolder() { Photo = photo, Name = name, Department = department };  
  44.             }  
  45.   
  46.             var holder = (ViewHolder)view.Tag;  
  47.   
  48.             holder.Photo.SetImageDrawable(ImageManager.Get(parent.Context, users[position].ImageUrl));  
  49.             holder.Name.Text = users[position].Name;  
  50.             holder.Department.Text = users[position].Department;  
  51.   
  52.   
  53.             return view;  
  54.   
  55.         } 
  56.     }   

The Custom Adapter is extended by the Base Adapter and it has some Abstract methods, as shown below.

  • Count- This method returns the count of the list items.
  • GetItemId- It returns the position of the item.
  • GetView- This method is used to bind the view to the ListView row, it will bind the data with the row.

Step 7

Now, create the Image Manager class, which is used to bind the images with the ImageView, as shown below.

(File Name: ImageManager.cs) 

  1. public static class ImageManager  
  2.     {  
  3.         static Dictionary<string, Drawable> cache = new Dictionary<string, Drawable>();  
  4.   
  5.         public static Drawable Get(Context context, string url)  
  6.         {  
  7.             if (!cache.ContainsKey(url))  
  8.             {  
  9.                 var drawable = Drawable.CreateFromStream(context.Assets.Open(url), null);  
  10.   
  11.                 cache.Add(url, drawable);  
  12.             }  
  13.   
  14.             return cache[url];  
  15.         }  
  16.     }   

In the code given above, the images are boud with the Assets folder. (Add the images to the Image folder accordingly).

Step 8

Now, we require data source for the list, so we will create UserData file to provide the data to the list, as shown below.

(File Name: UserData.cs) 

  1. public static class UserData  
  2.     {  
  3.         public static List<User> Users { get; private set; }  
  4.   
  5.         static UserData()  
  6.         {  
  7.             var temp = new List<User>();  
  8.   
  9.             AddUser(temp);  
  10.             AddUser(temp);  
  11.             AddUser(temp);  
  12.   
  13.             Users = temp.OrderBy(i => i.Name).ToList();  
  14.         }  
  15.   
  16.         static void AddUser(List<User> users)  
  17.         {  
  18.             users.Add(new User()  
  19.             {  
  20.                 Name = "aVirendra Thakur",  
  21.                 Department = "Xamarin Android & Xamarin Forms Development",  
  22.                 ImageUrl = "images/image.png",  
  23.                 Details = "Virendra has over 2 years of experience developing mobile applications,"               
  24.             });  
  25.   
  26.             users.Add(new User()  
  27.             {  
  28.                 Name = "bVirendra Thakur",  
  29.                 Department = "Xamarin Android & Xamarin Forms Development",  
  30.                 ImageUrl = "images/image2.png",  
  31.                 Details = "Virndra has over 2 years of experience developing mobile applications; specializing in Android & C# cross platform development."  
  32.   
  33.             });  
  34.             users.Add(new User()  
  35.             {  
  36.                 Name = "bVirendra Thakur",  
  37.                 Department = "Xamarin Android & Xamarin Forms Development",  
  38.                 ImageUrl = "images/image.png",  
  39.                 Details = "Virndra has over 2 years of experience developing mobile applications; specializing in Android & C# cross platform development."  
  40.   
  41.             });  
  42.   
  43.             users.Add(new User()  
  44.             {  
  45.                 Name = "aVirendra Thakur",  
  46.                 Department = "Xamarin Android & Xamarin Forms Development",  
  47.                 ImageUrl = "images/image2.png",  
  48.                 Details = "Virndra has over 2 years of experience developing mobile applications; specializing in Android & C# cross platform development."  
  49.   
  50.             }); users.Add(new User()  
  51.             {  
  52.                 Name = "dVirendra Thakur",  
  53.                 Department = "Xamarin Android & Xamarin Forms Development",  
  54.                 ImageUrl = "images/image.png",  
  55.                 Details = "Virndra has over 2 years of experience developing mobile applications; specializing in Android & C# cross platform development."  
  56.   
  57.            });  
  58. }   

Step 9

Create ViewHolder Class, which holds the controls of the view. It will only create the controls and reuse it in ListView, which saves the memory.

(File Name: ViewHolder.cs) 

  1. public class ViewHolder: Java.Lang.Object  
  2.     {  
  3.         public ImageView Photo { get; set; }  
  4.         public TextView Name { get; set; }  
  5.         public TextView Department { get; set; }  
  6.     }   

Step 10

Now, go to MyCustomListAdapter and add the few lines of code to bind the data, as shown below.

(File Name: MyCustomListAdapter.cs) 

  1. public override View GetView(int position, View convertView, ViewGroup parent)  
  2.         {  
  3.             var view = convertView;  
  4.   
  5.             if(view==null)  
  6.             {  
  7.                 view = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.userRow, parent, false);  
  8.   
  9.                 var photo = view.FindViewById<ImageView>(Resource.Id.photoImageView);  
  10.                 var name = view.FindViewById<TextView>(Resource.Id.nameTextView);  
  11.                 var department = view.FindViewById<TextView>(Resource.Id.departmentTextView);  
  12.   
  13.                 view.Tag = new ViewHolder() { Photo = photo, Name = name, Department = department };  
  14.             }  
  15.   
  16.             var holder = (ViewHolder)view.Tag;  
  17.   
  18.             holder.Photo.SetImageDrawable(ImageManager.Get(parent.Context, users[position].ImageUrl));  
  19.             holder.Name.Text = users[position].Name;  
  20.             holder.Department.Text = users[position].Department;  
  21.   
  22.   
  23.             return view;  
  24.   
  25.         }   

Step 11

Add the Custom Adapter to the ListView in MainActivity, as shown below. 

  1. protected override void OnCreate(Bundle bundle)  
  2.         {  
  3.             base.OnCreate(bundle);  
  4.   
  5.             // Set our view from the "main" layout resource  
  6.             SetContentView(Resource.Layout.Main);  
  7.   
  8.             myList = FindViewById<ListView>(Resource.Id.listView);  
  9.   
  10.             myList.Adapter = new MyCustomListAdapter(UserData.Users);  
  11.         }   

Output

Now, run the Application and you will see the output given below.