This is a tutorial about customzing a gridview with images and text. To achieve that we’ll need a custom adapter to help in inflation of our custom layouts and binding of data onto them.

So we’ll create a Custom Adapter based on BaseAdapter.

Uses of GridView

No. Responsibility
1. Display data in columned grids.

Advantages of GridView

No. Responsibility
1. It’s easy to customize.
2. It supports several adapters.

1. Create Project

  1. Create New Xamarin Android Project.
  2. Choose blank app:

Create Xamarin Project

2. Create User Interface

User interfaces in Xamarin Android can be created either imperatively by java code or declaratively by AXML, Microsoft’s subset of XML(eXtensible Markup Language).

(a). Main.axml

This is our MainActivity layout.

Here are it’s roles:

No. Responsibility
1. Hold our GridView which will be our adapterview.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <GridView
        android:id="@+id/gv"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:numColumns="3"
        android:background="#eeee" />
</LinearLayout>

(b). Model.axml

This is our custom grids layout.

Here are it’s roles:

No. Responsibility
1. Define an ImageView to be used to show our Fruit object image.
2. Define a TextView to be used to render the name of a fruit.
3. Hold these two widgets vertically using a LinearLayout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:src="@drawable/mango"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/fruitImg"
        android:layout_marginRight="0.0dp"
        android:padding="15dp" />
    <TextView
        android:text="Name"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_width="wrap_content"
        android:layout_height="90dp"
        android:padding="15dp"
        android:id="@+id/nameTxt"
        android:layout_toRightOf="@+id/fruitImg"
        android:layout_alignParentRight="true"
        android:textColor="#000" />
</LinearLayout>

Our classes.

3. Fruit.cs

This is our data object. It represents a single Fruit.

No. Responsibility
1. Define two private instance fields of a Fruit: name and image.
2. Obtain values and assign them to these instance fields via a public constructor.
3. Define two public properties Name and Image to expose our two instance fields.
using System;

namespace Custom_GridView_BaseAdapter
{
    class Fruit
    {
        private String name;
        private int image;

        public Fruit(string name, int image)
        {
            this.name = name;
            this.image = image;
        }

        public string Name
        {
            get { return name; }
        }

        public int Image
        {
            get { return image; }
        }
    }
}

4. CustomAdapter.cs

This is our Adapter class.

No. Responsibility
1. Accept the responsibilities of an adapter by deriving from Android.Widget.BaseAdapter.
2. Define three private instance fields: Context, JavaList and LayoutInflater objects.
3. Receive a Context object and a JavaList object via the constructor and assign them to our local instance fields.
4. Override the GetItem() method which returns an Fruit Object from our JavaList.
5. Use the position of a single fruit as it’s unique identifier.
6. Use our LayoutInflater to inflate the layout Model.axml into a View object and return that View object.
7. Bind our image and text properties from each Fruit object to our imageview and textviews respectively.

using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Object = Java.Lang.Object;

namespace Custom_GridView_BaseAdapter
{
    class CustomAdapter : BaseAdapter
    {
        private Context c;
        private JavaList<Fruit> fruits;
        private LayoutInflater inflater;

        public CustomAdapter(JavaList<Fruit> fruits, Context c)
        {
            this.fruits = fruits;
            this.c = c;
        }

        public override Object GetItem(int position)
        {
            return fruits.Get(position);
        }

        public override long GetItemId(int position)
        {
            return position;
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            if (inflater == null)
            {
                inflater = (LayoutInflater) c.GetSystemService(Context.LayoutInflaterService);
            }

            if (convertView == null)
            {
                convertView = inflater.Inflate(Resource.Layout.Model, parent, false);
            }

            //BIND DATA
            TextView nameTxt = convertView.FindViewById<TextView>(Resource.Id.nameTxt);
            ImageView img = convertView.FindViewById<ImageView>(Resource.Id.fruitImg);

            nameTxt.Text = fruits[position].Name;
            img.SetImageResource(fruits[position].Image);

            return convertView;
        }

        public override int Count
        {
            get { return fruits.Size(); }
        }
    }
}

5. MainActivity.cs

Our MainActivity class.

Here are the roles of this class:

No. Responsibility
1. Allow itself to become a xamarin android activity component by inheriting from Android.App.Activity.
2. Listen to activity creation callbacks by overrding the OnCreate() method.
3. Invoke the OnCreate() method of the base Activity class and pass it a Bundle object we’ve received.
4. Inflate the Main.axml into a View object and set it as the content view of this activity.
5. Define three private instance fields: GridView, CustomAdapter and JavaList objects.
6. Define a private method GetFruits() that returns a JavaList<Fruit> after populating it with Fruit objects.
7. Search a Gridview by it’s id and assign it to our GridView instance field.
8. Instantiate our CustomAdapter passing it our data source as well as Context.
9. Set the adapter as a property of our GridView.
10. Listen to our Custom GridView click events hence showing a Toast message.
using Android.App;
using Android.Runtime;
using Android.Widget;
using Android.OS;

namespace Custom_GridView_BaseAdapter
{
    [Activity(Label = "Custom GridView BaseAdapter", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {

        private GridView gv;
        private CustomAdapter adapter;
        private JavaList<Fruit> fruits; 

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            gv = FindViewById<GridView>(Resource.Id.gv);

            adapter=new CustomAdapter(GetFruits(),this);

            gv.Adapter = adapter;

            gv.ItemClick += gv_ItemClick;
        }

        void gv_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
        {
            Toast.MakeText(this,fruits[e.Position].Name,ToastLength.Short).Show();
        }

        //POPULATE FRUITS
        private JavaList<Fruit> GetFruits()
        {
            fruits = new JavaList<Fruit>();

            Fruit f;

            f = new Fruit("Apple", Resource.Drawable.apples);
            fruits.Add(f);

            f = new Fruit("Oranges", Resource.Drawable.oranges);
            fruits.Add(f);

            f = new Fruit("Pineapple", Resource.Drawable.pineapple);
            fruits.Add(f);

            f = new Fruit("Apples", Resource.Drawable.apples);
            fruits.Add(f);

            f = new Fruit("Mango", Resource.Drawable.mango);
            fruits.Add(f);

            f = new Fruit("Grapes", Resource.Drawable.grapes);
            fruits.Add(f);

            return fruits;
        }
    }
}