By Mohamad Wael

Posted :

GridView in android a tutorial

A GridView is simply a grid of views , it is a subclass of AbsListView , so the methods and fields defined for AbsListView , apply to a GridView . Another subclass of AbsListView is Listview .

This tutorial will show how to create a GridView , the final product is shown below .

Start by defining the layout of the MainActivity activity_main.xml , which contains a single child , the GridView :

<!-- activity_main.xml in the layout folder .-->

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    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="match_parent"
        android:layout_height="match_parent"
        android:numColumns="3"
        android:stretchMode="columnWidth"
        android:horizontalSpacing="8dp"
        android:verticalSpacing="16dp"
        android:listSelector="@drawable/grid_item_selected"
        android:padding="8dp" >
    </GridView>

</FrameLayout>

The android:stretchMode attribute is related to the remaining space , and is used to specify how the remaining available space is divided . By default it has a value of android:stretchMode="columnWidth" , which is columns will be equally stretched . If set to android:stretchMode="none" , then the remaining space is not stretched , if set to spacingWidth , then the remaining space is stretched equally between columns , if set to spacingWidthUniform , then the remaining space is divided equally around and between the columns .

The android:numColumns attribute is used to specify the number of columns . If set to android:numColumns="auto_fit" , and no android:columnWidth attribute is set , then the number of columns is set to 2 . If set to android:numColumns="auto_fit" and android:columnWidth is set to a value , as in android:columnWidth="20dp" , then the number of column is calculated based on the available remaining space , while guarding the set horizontal spacing , in other words , factoring out horizontal spacing .

If the number of columns is set , then it is the set number of columns . If the number of columns is not set or is set to a negative value , then it is set to 1 .

android:stretchMode is always applied as specified , so for example , setting a number of column , and no column width , if the stretchMode is set to columnWidth , then the available space , factoring out any horizontal spacing , is divided evenly between the set number of columns .

Horizontal spacing between columns , and vertical spacing between rows , can be set using android:horizontalSpacing , and android:verticalSpacing .

The android:listSelector is used to specify an effect , when an item in the grid is selected . In this example , a drawable android:listSelector="@drawable/grid_item_selected" has been specified as the effect , which is setting the background color to orange . The drawable has been defined in the drawable folder , and has the following code :

<!-- grid_item_selected.xml in the drawable folder .-->    
   
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
            android:drawable="@android:color/holo_orange_light"/>
</selector>

Having defined the GridView and its attributes , the layout for an item in the GridView must be defined , as follows :

<!-- grid_item.xml in the layout folder .-->     

<?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="wrap_content">

    <ImageView
        android:id="@+id/ivPhoto"
        android:layout_width="match_parent"
        android:layout_height="90dp"
        android:background="@android:color/black" />

    <TextView
        android:id="@+id/tvLabel"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp" />
</LinearLayout>

Having defined the layout for an item , a controller must be created , to manage the items of a GridView , as for example , their creation , and data connection . This is done by extending the BaseAdapter class , as follows :

/* GridView_Controller.java */

package com.twiserandom.mobileapps.demo.gridview;

import android .content .Context;

import android .view .View;
import android .view .ViewGroup;

import android .widget .BaseAdapter;
import android .widget .ImageView;
import android .widget .TextView;

public class
        GridView_Controller
            extends BaseAdapter {

    private int image_ids [ ] = {R .drawable .img_001_forest ,  R .drawable .img_002_mountain ,
                                 R .drawable .img_003_mountain_close_view ,
                                 R .drawable .img_004_mountain_sea ,
                                 R .drawable .img_005_sea_sand };
    private String image_label [ ] = {"Forest" , "Mountain" ,
                                      "Mountain Close View" ,
                                      "Mountain Sea",
                                      "Sea Sand" };
    private Context context;

    GridView_Controller
            (Context context ){
        this .context = context; }

    class Image {
        String image_name;
        int image_id;

        Image
                (String image_name , int image_id ){
            this .image_name = image_name ;
            this .image_id = image_id ; } }

    @Override
    public int
            getCount 
                ( ){/* Return the data 
                Count */
        return image_ids .length ; }

    @Override
    public Object
            getItem
                (int position ){/* Return an object 
                    representing the data at the 
                    given position , to be retrieved 
                    later on , for example when 
                    handling click events . Can 
                    return null , if have nothing 
                    to pass on .*/
        return new Image (image_label [position ] , image_ids [position ] );}

    @Override
    public long
            getItemId
                (int position ){/* Can return -1 , or 0 , 
                    if do not have own ids to pass on .
                    If have own generated identifiers , 
                    they can be passed here , to be retrieved 
                    later on , for example when handling 
                    click events .*/ 
        return image_ids [position ]; }

    @Override
    public View 
            getView
                (int position , View convertView , ViewGroup parent ){/*
                    Return an item's View .*/

        if (convertView == null ){/* Views are recyclable , so 
            this means they are reusable , so only inflate 
            a view if it is not null .*/
            convertView = View .inflate (context , R .layout .grid_item , null ); }

        ImageView ivPhoto = convertView .findViewById (R .id .ivPhoto );
        ivPhoto .setImageResource (image_ids [position ] );

        TextView tvLabel = convertView .findViewById (R .id .tvLabel );
        tvLabel .setText (image_label [position ] );

        return convertView; } }

Now it is time to create the MainActivity class , in the MainActivity.java file . This class will connect the controller to the GridView , and it will set an OnItemClickListener, for the GridView .

/* MainActivity.java */

package com .twiserandom .mobileapps .demo .gridview;

import androidx .appcompat .app .AppCompatActivity;

import android .os .Bundle;

import android .view .View;

import android .widget .AdapterView;
import android .widget .GridView;
import android .widget .Toast;

public class
        MainActivity
            extends AppCompatActivity {

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

        GridView gridView = findViewById (R .id .gridView );
        gridView .setAdapter (new GridView_Controller (this ) ); /* Connect 
            the controller to the GridView .*/
        gridView .setOnItemClickListener (new AdapterView .OnItemClickListener ( ){
            @Override
            public void
                    onItemClick
                        (AdapterView  parent , View view , int position , long id ){
                GridView_Controller .Image image =
                        (GridView_Controller .Image ) parent .getItemAtPosition (position );/*
                        Get the attached data .*/
                Toast .makeText (MainActivity .this ,
                        image .image_name + " " + id , Toast.LENGTH_LONG )
                      .show ( ); /* Show 
                      a toast , containing the attached data , 
                      and the generated ID .*/ } });}}