RecyclerView StaggeredGridLayoutManager allows to lay out items of recyclerView in a staggered grid format , Lets see example .
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
<?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 .
- 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.
- onBindViewHolder() : Inside this method data will be displayed at the specified position .
- getItemCount() : Returns the total number of items in the data set held by the adapter.
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
- spanCount : If orientation is vertical, spanCount is number of columns. If orientation is horizontal, spanCount is number of rows.
- orientation : Sets the orientation (VERTICAL HORIZONTAL).
recyclerView.layoutManager = StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)
Activity
- Create a koltin class MainActivity.kt and extend it to AppCompatActivity class .
- Override onCreate function and set the content of this MainActivity with above defined xml layout (activity_main.xml).
- Read JSON Data From Asset Folder , this will be used for binding data into RecyclerView .
- Set StaggeredGridLayoutManager to RecyclerView.
- Create Instance of Adapter and set to RecyclerView .
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 } }
1 comment:
nice
Post a Comment