Android RecyclerView StaggeredGrid Layout

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  StaggeredGridLayoutManager  allows to lay out items of recyclerView in a staggered grid format , Lets see example .



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

XML 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 StaggeredGrid 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:background="@drawable/circle_bg"
        android:gravity="center"
        android:orientation="vertical">

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

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

    <TextView
            android:id="@+id/sub_txt"
            android:textSize="16sp"
            android:text="Title"
            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.recyclerviewstaggeredgrid.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 StaggeredGridLayoutManager To RecyclerView 


StaggeredGridLayoutManager  : 

StaggeredGridLayoutManager is a subclass of RecyclerView.LayoutManager , A LayoutManager that lays out children in a staggered grid formation . It supports horizontal & vertical layout as well as an ability to layout children in reverse .

StaggeredGridLayoutManager(int spanCount, int orientation)

The Above  Constructor Creates Vertical StaggeredGridLayoutManager and it takes  two parameters
  1. spanCount : If orientation is vertical, spanCount is number of columns. If orientation is horizontal, spanCount is number of rows.
  2. orientation : Sets the orientation (VERTICAL HORIZONTAL).
Create an instance of StaggeredGridLayoutManager and set it to recyclerView layoutManager.

recyclerView.layoutManager = StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)

Activity

  1. Create a koltin class MainActivity.kt and extend it to AppCompatActivity class .
  2. Override onCreate function and set the content of this MainActivity with above defined xml layout (activity_main.xml). 
  3. Read JSON Data From Asset Folder , this will be used for binding data into RecyclerView .
  4. Set StaggeredGridLayoutManager to RecyclerView.
  5. Create Instance of Adapter and set to RecyclerView .
file : MainActivity.kt
package com.tutorialsbuzz.recyclerviewstaggeredgrid

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.recyclerview.widget.StaggeredGridLayoutManager
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 = StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)
        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
    }

}


RecyclerView Related
  1. RecyclerView
  2. RecyclerView Item Click Ripple Effect
  3. RecyclerView With Item Divider
  4. RecyclerView With CardView
  5. RecyclerView GridLayout
  6. RecyclerView StaggeredGrid Layout
  7. RecyclerView Swipe To Delete
  8. Android RecyclerView Swipe to Delete Undo
  9. Android RecyclerView Interactive Swipe Like Gmail

1 comment:

Post a Comment