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. // Set our view from the "main" layout resource
  9. SetContentView(Resource.Layout.Main);
  10. myList = FindViewById<ListView>(Resource.Id.listView);
  11. }
  12. }

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. public override string ToString()
  8. {
  9. return Name + " " + Department;
  10. }
  11. }

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

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

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. public static Drawable Get(Context context, string url)
  5. {
  6. if (!cache.ContainsKey(url))
  7. {
  8. var drawable = Drawable.CreateFromStream(context.Assets.Open(url), null);
  9. cache.Add(url, drawable);
  10. }
  11. return cache[url];
  12. }
  13. }

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

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. if(view==null)
  5. {
  6. view = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.userRow, parent, false);
  7. var photo = view.FindViewById<ImageView>(Resource.Id.photoImageView);
  8. var name = view.FindViewById<TextView>(Resource.Id.nameTextView);
  9. var department = view.FindViewById<TextView>(Resource.Id.departmentTextView);
  10. view.Tag = new ViewHolder() { Photo = photo, Name = name, Department = department };
  11. }
  12. var holder = (ViewHolder)view.Tag;
  13. holder.Photo.SetImageDrawable(ImageManager.Get(parent.Context, users[position].ImageUrl));
  14. holder.Name.Text = users[position].Name;
  15. holder.Department.Text = users[position].Department;
  16. return view;
  17. }

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. // Set our view from the "main" layout resource
  5. SetContentView(Resource.Layout.Main);
  6. myList = FindViewById<ListView>(Resource.Id.listView);
  7. myList.Adapter = new MyCustomListAdapter(UserData.Users);
  8. }

Output

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