Android RecyclerView GridLayout

RecyclerView is a ViewGroup ,that display a scrolling list of elements based on large data sets (or data that frequently changes) . RecyclerView widget is more flexible and efficient version of ListView .

RecyclerView's GridLayoutManger allows to lay out items of recyclerView in grid format , Lets see example .



Project Detail
Project Name RecyclerViewGrid
Package com.tutorialsbuzz.recyclerviewgrid
Min Sdk Version 22
Target Sdk Version 29
Compile Sdk Version 29
Theme Theme.AppCompat.Light.DarkActionBar

Add RecyclerView to your layout



Create XML Layout activity_main.xml , this will be set as content view for launcher Activity (MainActivity.kt) and add RecyclerView to your layout file

file : activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
        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"
        android:id="@+id/recyclerView"/>

Data Class


file : Model.kt
package com.tutorialsbuzz.recyclerview

data class Model(val name: String, val version: String) {}


To Load Data Into RecyclerView , We will read JSON File Kept Inside Asset folder and map it to above defined data class .

file : main\assets\android_version.json
[
  {
    "name": "Cupcake",
    "version": "Android 1.5"
  },
  {
    "name": "Donut",
    "version": "Android 1.6"
  },
  {
    "name": "Eclairs",
    "version": "Android 2.0-2.1"
  },
  {
    "name": "Froyo",
    "version": "Android 2.2-2.3"
  },
  {
    "name": "Gingerbread",
    "version": "Android 2.3-2.3.7"
  },
  {
    "name": "Honeycomb",
    "version": "Android 3.0-3.2.6"
  },
  {
    "name": "Icecream",
    "version": "Android 4.0-4.0.4"
  },
  {
    "name": "Jellybean",
    "version": "Android 4.1-4.3.1"
  },
  {
    "name": "Kitkat",
    "version": "Android 4.4-4.4.4"
  },
  {
    "name": "Lolipop",
    "version": "Android 5.0-5.1.1"
  },
  {
    "name": "Marshmallow",
    "version": "Android 6.0-6.0.1"
  },
  {
    "name": "Nougat",
    "version": "Android 7.0-7.1.2"
  },
  {
    "name": "Oreo",
    "version": "Android 8.0-8.1"
  },
  {
    "name": "Pie",
    "version": "Android 9.0"
  }
]


Image Resource 

Name field from json matches to respective png file name kept inside drawable .

Folder : app\src\main\res\drawable

Adapter and ViewHolder For RecyclerView .


1. Create Grid Cell Layout
 
Create XML Layout file in res/layout and name it row_item.xml .

file : row_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="18dp"
        android:gravity="center"
        android:orientation="vertical">

    <com.tutorialsbuzz.recyclerviewgrid.CirleImageView
            android:layout_width="60dp"
            android:layout_height="60dp"
            app:civ_border_width="8dp"
            app:civ_border_color="#e5e5e5"
            android:id="@+id/img"
            android:contentDescription="@string/app_name"/>

    <TextView
            android:id="@+id/txt"
            android:textSize="14sp"
            android:text="Title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:textStyle="bold"/>

    <TextView
            android:id="@+id/sub_txt"
            android:textSize="14sp"
            android:text="Title"
            android:visibility="gone"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="italic"/>

</LinearLayout>

2. Adapter class

Create a Adapter That RecyclerView Can Use ,Create a class CustomAdapter extend it to RecyclerView.Adapter .

RecyclerView.Adapter has three abstract methods that we must override .
  1. onCreateViewHolder() : Inside this method we specify the layout that each item of the RecyclerView should use .onCreateViewHolder has return type of RecyclerView.ViewHolder which represent each row of recyclerView . Using Inflator get the view of above defined row_item and pass it to viewholder constructor and then return.
  2. onBindViewHolder() : Inside this method data will be displayed at the specified position .
  3. getItemCount() : Returns the total number of items in the data set held by the adapter.

3. ViewHolder

Create Inner class ViewHolder extend it to RecyclerView.ViewHolder , add bind function which takes above defined model data class object 

file : CustomAdapter.kt
package com.tutorialsbuzz.recyclerview

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.tutorialsbuzz.recyclerviewgrid.R
import kotlinx.android.synthetic.main.row_item.view.*


class CustomAdapter(val modelList: List<Model>, val context: Context) :
    RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        (holder as ViewHolder).bind(modelList.get(position));
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        return ViewHolder(layoutInflater.inflate(R.layout.row_item, parent, false))
    }


    override fun getItemCount(): Int {
        return modelList.size;
    }

    lateinit var mClickListener: ClickListener

    fun setOnItemClickListener(aClickListener: ClickListener) {
        mClickListener = aClickListener
    }

    interface ClickListener {
        fun onClick(pos: Int, aView: View)
    }

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {

        init {
            itemView.setOnClickListener(this)
        }

        override fun onClick(p0: View?) {
            mClickListener.onClick(adapterPosition, itemView)
        }

        fun bind(model: Model): Unit {
            itemView.txt.text = model.name
            itemView.sub_txt.text = model.version

            val id = context.resources.getIdentifier(model.name.toLowerCase(), "drawable", context.packageName)
            itemView.img.setImageResource(id)
        }

    }

}

Applying GridLayoutManger To RecyclerView 


GridLayoutManger is a subclass of RecyclerView.LayoutManager , This class lay out items of recyclerView in grid format .
GridLayoutManager(Context context, int spanCount)

 The Above  Constructor Creates Vertical GridLayoutManager and it takes  two parameters   
  1.  Context: Current context, will be used to access resources.
  2.  int: The number of columns in the grid 
Create an instance of GridLayoutManager and set it to recyclerView layoutManager.

recyclerView.layoutManager = GridLayoutManager(this, 4)

Activity


  1. Override onCreate function and set the content of this MainActivity with above defined xml layout (activity_main.xml). 
  2. Read JSON Data From Asset Folder , this will be used for binding data into RecyclerView .
  3. Set GridLayoutManager to RecyclerView.
  4. Create Instance of Adapter and set to RecyclerView .

file : MainActivity.kt
package com.tutorialsbuzz.recyclerviewgrid

import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import com.tutorialsbuzz.recyclerview.CustomAdapter
import com.tutorialsbuzz.recyclerview.Model
import kotlinx.android.synthetic.main.activity_main.*
import org.json.JSONArray
import org.json.JSONObject

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val model = readFromAsset();

        val adapter = CustomAdapter(model, this)

        recyclerView.layoutManager = GridLayoutManager(this, 4)
        recyclerView.adapter = adapter;
        adapter.setOnItemClickListener(object : CustomAdapter.ClickListener {
            override fun onClick(pos: Int, aView: View) {
                Toast.makeText(this@MainActivity, model.get(pos).name, Toast.LENGTH_SHORT).show()
            }
        })
    }


    private fun readFromAsset(): List<Model> {

        val modeList = mutableListOf<Model>()

        val bufferReader = application.assets.open("android_version.json").bufferedReader()
        val json_string = bufferReader.use {
            it.readText()
        }

        val jsonArray = JSONArray(json_string);
        for (i in 0..jsonArray.length() - 1) {
            val jsonObject: JSONObject = jsonArray.getJSONObject(i)
            val model = Model(jsonObject.getString("name"), jsonObject.getString("version"))
            modeList.add(model)
        }
        return modeList
    }

}


No comments:

Post a comment