o7planning

Android GridView Tutorial with Examples

  1. What is GridView?
  2. Basic GridView using ArrayAdapter
  3. Customizing GridView using BaseAdapter

1. What is GridView?

GridView is a view group that shows items in two-dimensional scrolling grid.
GridItem
An Android GridView is made from a group of GridItem(s). GridItems are individual cels in gridview where the data will be displayed. Any data in gridview is displayed only through griditem.
A Griditem is a piece of the interface which can be created by a number of View.

Android builds some several different Grid Item forms, called the pre-defined layout, which will be mentioned in the examples of this document.

Adapter
Android Adapter is a bridge between the View and the underlying data for that view. An adapter manages the data and adapts the data to the individual cell (gridItems) of the view.

You can bind the adapter with Android gridview via setAdapter method. Now, Let us see how Adapter works with the help of the following image.
GridView Selector
To make GridView become more beautiful, you need to customize the effects, such as changing the background color of GridItem when cursor moves over it, or change background color when it is selected. You can see an example for customizing GridView Selector in the end of this document.

2. Basic GridView using ArrayAdapter

ArrayAdapter
ArrayAdapter used to display the GridView with simple GridItem, GridItem can be made from only one TextView, CheckedTextView, EditText, ...

In case where you want to have a GridView with more complex GridItem, you can manually create a customized Adapter.
GridView with ArrayAdapter example
Create Android project named SimpleGridView.
  • File > New > New Project > Empty Activity
    • Name: SimpleGridView
    • Package name: org.o7planning.simplegridview
    • Language: Java
Design the UI:
Change GridView properties:
GridView
  • android:numColumns ="2"
  • android:stretchMode ="columnWidth"
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <GridView
        android:id="@+id/gridView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginBottom="16dp"
        android:numColumns="2"
        android:stretchMode="columnWidth"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Website.java
package org.o7planning.simplegridview;

public class Website {

    private String name;
    private String url;

    public Website(String name, String url)  {
        this.name= name;
        this.url= url;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString()  {
        return name;
    }
}
MainActivity.java
package org.o7planning.simplegridview;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private GridView gridView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.gridView = (GridView)findViewById(R.id.gridView);

        //

        Website o7planning = new Website("o7planning","http://o7planning.org");
        Website google = new Website("Google","http://google.com");
        Website facebook = new Website("Facebook","http://facebook.com");
        Website eclipse = new Website("Eclipse","http://eclipse.org");
        Website yahoo = new Website("Yahoo","http://yahoo.com");

        Website[] websites = new Website[]{o7planning,google, facebook,eclipse, yahoo};

        // android.R.layout.simple_list_item_1 is a constant predefined layout of Android.
        // used to create a GridView with simple GridItem (Only one TextView).

        ArrayAdapter<Website> arrayAdapter
                = new ArrayAdapter<Website>(this, android.R.layout.simple_list_item_1 , websites);


        gridView.setAdapter(arrayAdapter);

        // When the user clicks on the GridItem
        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> a, View v, int position, long id) {
                Object o = gridView.getItemAtPosition(position);
                Website website = (Website) o;
                Toast.makeText(MainActivity.this, "Selected :" + " " + website.getName()+"\n("+ website.getUrl()+")",
                        Toast.LENGTH_LONG).show();
            }
        });
    }

}
Running the example:
The layouts is available to work with ArrayAdapter
Android built some Layout (for Grid Item, List Item, ..) can work with ArrayAdapter.
android.R.layout.simple_list_item_1
  • This is a simple layout of GridItem, created by single TextView (You can see examples above).
android.R.layout.simple_list_item_checked & android.R.layout.simple_list_item_multiple_choice
  • Two Layout above are the simple layouts to create a GridView with GridItem created by single checkbox.
  • TODO

    3. Customizing GridView using BaseAdapter

    You can customize a GridView. Your Adapter should extend from BaseAdapter class.
    Custom GridView example
    Create new project named CustomGridView.
    • File > New > New Project > Empty Activity
      • Name: CustomGridView
      • Package name: org.o7planning.customgridview
      • Language: Java
    Preview application:
    Firstly you need to prepare some images:
    Copy and paste the image file into the mipmap folder:
    vn.png
    us.png
    ru.png
    jp.png
    au.png
    You need to create a layout for griditem. In Android Studio right-click the res/layout and selecte:
    • New/Layout resource file
    Enter:
    • File name: grid_item_layout.xml
    • Root element: androidx.constraintlayout.widget.ConstraintLayout
    Interface Design for Grid-Item.
    Slider, interface design steps for GridItem:
    ImageView
    • ID: imageView_flag

    TextView 1:
    • ID: textView_countryName
    • Text: Country Name

    TextView 2:
    • ID: textView_population
    • Text: Population ....
    grid_item_layout.xml
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ImageView
            android:id="@+id/imageView_flag"
            android:layout_width="80dp"
            android:layout_height="60dp"
            android:layout_marginStart="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginTop="8dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/ic_launcher_foreground" />
    
        <TextView
            android:id="@+id/textView_countryName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginRight="8dp"
            android:text="Country Name"
            android:textSize="18sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/imageView_flag"
            app:layout_constraintTop_toTopOf="parent" />
    
        <TextView
            android:id="@+id/textView_population"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginTop="3dp"
            android:layout_marginEnd="8dp"
            android:layout_marginRight="8dp"
            android:text="Population"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/imageView_flag"
            app:layout_constraintTop_toBottomOf="@+id/textView_countryName" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    activity_main.xml
    GridView
    • android:numColumns ="2"
    • android:stretchMode ="columnWidth"
    activity_main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <GridView
            android:id="@+id/gridView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginStart="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginBottom="8dp"
            android:numColumns="2"
            android:stretchMode="columnWidth"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    CustomGridAdapter is a class extending from BaseAdapter, it is used to display data on the GridItem.
    Country.java
    package org.o7planning.customgridview;
    
    public class Country {
    
        private String countryName;
    
        // Image name (Without extension)
        private String flagName;
        private int population;
    
        public Country(String countryName, String flagName, int population) {
            this.countryName= countryName;
            this.flagName= flagName;
            this.population= population;
        }
    
        public int getPopulation() {
            return population;
        }
    
        public void setPopulation(int population) {
            this.population = population;
        }
    
        public String getCountryName() {
            return countryName;
        }
    
        public void setCountryName(String countryName) {
            this.countryName = countryName;
        }
    
        public String getFlagName() {
            return flagName;
        }
    
        public void setFlagName(String flagName) {
            this.flagName = flagName;
        }
    
        @Override
        public String toString()  {
            return this.countryName+" (Population: "+ this.population+")";
        }
    }
    CustomGridAdapter.java
    package org.o7planning.customgridview;
    
    import android.content.Context;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    import java.util.List;
    
    public class CustomGridAdapter  extends BaseAdapter {
    
        private List<Country> listData;
        private LayoutInflater layoutInflater;
        private Context context;
    
        public CustomGridAdapter(Context aContext,  List<Country> listData) {
            this.context = aContext;
            this.listData = listData;
            layoutInflater = LayoutInflater.from(aContext);
        }
    
        @Override
        public int getCount() {
            return listData.size();
        }
    
        @Override
        public Object getItem(int position) {
            return listData.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                convertView = layoutInflater.inflate(R.layout.grid_item_layout, null);
                holder = new ViewHolder();
                holder.flagView = (ImageView) convertView.findViewById(R.id.imageView_flag);
                holder.countryNameView = (TextView) convertView.findViewById(R.id.textView_countryName);
                holder.populationView = (TextView) convertView.findViewById(R.id.textView_population);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
    
            Country country = this.listData.get(position);
            holder.countryNameView.setText(country.getCountryName());
            holder.populationView.setText("" + country.getPopulation());
    
            int imageId = this.getMipmapResIdByName(country.getFlagName());
    
            holder.flagView.setImageResource(imageId);
    
            return convertView;
        }
    
        // Find Image ID corresponding to the name of the image (in the directory mipmap).
        public int getMipmapResIdByName(String resName)  {
            String pkgName = context.getPackageName();
    
            // Return 0 if not found.
            int resID = context.getResources().getIdentifier(resName , "mipmap", pkgName);
            Log.i("CustomGridView", "Res Name: "+ resName+"==> Res ID = "+ resID);
            return resID;
        }
    
        static class ViewHolder {
            ImageView flagView;
            TextView countryNameView;
            TextView populationView;
        }
    
    }
    ActivityMain.java
    package org.o7planning.customgridview;
    
    import androidx.appcompat.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.GridView;
    import android.widget.ListView;
    import android.widget.Toast;
    import java.util.ArrayList;
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
    
            List<Country> image_details = getListData();
            final GridView gridView = (GridView) findViewById(R.id.gridView);
            gridView.setAdapter(new CustomGridAdapter(this, image_details));
    
            // When the user clicks on the GridItem
            gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    
                @Override
                public void onItemClick(AdapterView<?> a, View v, int position, long id) {
                    Object o = gridView.getItemAtPosition(position);
                    Country country = (Country) o;
                    Toast.makeText(MainActivity.this, "Selected :"
                            + " " + country, Toast.LENGTH_LONG).show();
                }
            });
        }
    
        private  List<Country> getListData() {
            List<Country> list = new ArrayList<Country>();
            Country vietnam = new Country("Vietnam", "vn", 98000000);
            Country usa = new Country("United States", "us", 320000000);
            Country russia = new Country("Russia", "ru", 142000000);
            Country australia = new Country("Australia", "au", 23766305);
            Country japan = new Country("Japan", "jp", 126788677);
    
            list.add(vietnam);
            list.add(usa);
            list.add(russia);
            list.add(australia);
            list.add(japan);
    
            return list;
        }
    
    }
    Running the app:
    Custom Selector example
    To make GridView become more beautiful, you need to customize the effects, such as changing the background color of GridItem when cursor moves over it, or change background color when it is selected. We continue with the example above.
    Create the configuration files:
    • File name: item_state_normal.xml
    • Directory: drawable
    Similarly create three different files:
    • item_state_pressed.xml
    • item_state_selected.xml
    • list_selector.xml
    When the grid item in a normal state, styles which is set up in item_state_normal.xml will be applied to the GridItem.
    item_state_normal.xml
    <?xml version="1.0" encoding="utf-8"?>
    
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
      android:shape="rectangle">
    
      <gradient
          android:startColor="#f1f1f2"
          android:centerColor="#e7e7e8"
          android:endColor="#cfcfcf"
          android:angle="270" />
    
    </shape>
    When Grid Item is pressed, the styles set up in item_state_pressed.xml will be applied to the GridItem
    item_state_pressed.xml
    <?xml version="1.0" encoding="utf-8"?>
    
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
      android:shape="rectangle">
    
      <gradient
          android:startColor="#18d7e5"
          android:centerColor="#16cedb"
          android:endColor="#09adb9"
          android:angle="270" />
    
    </shape>
    When Grid Item is selected, the styles set up in item_state_selected.xml will be applied to the GridItem
    item_state_selected.xml
    <?xml version="1.0" encoding="utf-8"?>
    
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    
       <gradient
           android:startColor="#18d7e5"
           android:centerColor="#16cedb"
           android:endColor="#09adb9"
           android:angle="270" />
    
    </shape>
    Mapping the specific status of the ListItem with xml files.
    list_selector.xml
    <?xml version="1.0" encoding="utf-8"?>
    
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
           <item
               android:state_selected="false"
               android:state_pressed="false"
               android:drawable="@drawable/item_state_normal" />
    
           <item android:state_pressed="true"
               android:drawable="@drawable/item_state_pressed" />
    
           <item android:state_selected="true"
               android:state_pressed="false"
               android:drawable="@drawable/item_state_selected" />
    
    
    </selector>
    Set ListSelector for GridView:
    <GridView
         ...
         android:listSelector="@drawable/list_selector" />
    activity_main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <GridView
            android:id="@+id/gridView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginStart="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginBottom="8dp"
            android:numColumns="2"
            android:stretchMode="columnWidth"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:listSelector="@drawable/list_selector" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    Rerun your application:

    Android Programming Tutorials

    Show More