A simple way to create different view types in RecyclerView Android
Learn how to create a RecyclerView with multiple type of layouts.
If your app needs to display a scrolling list of elements based on large data sets (or data that frequently changes), you should use RecyclerView
The RecyclerView
widget is a more advanced and flexible version of ListView
.
In the RecyclerView
model, several different components work together to display your data. The overall container for your user interface is a RecyclerView
object that you add to your layout. The RecyclerView
fills itself with views provided by a layout manager that you provide. You can use one of the standard layout managers (such as LinearLayoutManager
or GridLayoutManager
), or implement your own.
Add the support library
To access the RecyclerView
widget, you need to add the v7 Support Libraries to your project as follows:
- Open the
build.gradle
file for your app module. - Add the support library to the
dependencies
section.
dependencies {
implementation 'com.android.support:recyclerview-v7:28.0.0'
}
Add RecyclerView to your layout
Now you can add the RecyclerView
to your layout file. For example, the following layout uses RecyclerView
as the only view for the whole layout:
<?xml version="1.0" encoding="utf-8"?>
<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Once you have added a RecyclerView
widget to your layout, obtain a handle to the object, connect it to a layout manager, and attach an adapter for the data to be displayed:
class MyActivity : Activity(), OnListActivityInteractionListener {
private lateinit var recyclerView: RecyclerView
private lateinit var viewAdapter: RecyclerView.Adapter<*>
private lateinit var viewManager: RecyclerView.LayoutManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.my_activity)
viewManager = LinearLayoutManager(this)
viewAdapter = MyAdapter(myDataset, this)
recyclerView = findViewById<RecyclerView>(R.id.my_recycler_view).apply {
// use this setting to improve performance if you know that changes
// use a linear layout manager
layoutManager = viewManager
// specify an viewAdapter (see also next example)
adapter = viewAdapter
}
}
}
Interface
interface OnListActivityInteractionListener {
fun onListFragmentInteraction(item: Item)
}
Add a list adapter
To feed all your data to the list, you must extend the RecyclerView.Adapter
class. This object creates views for items, and replaces the content of some of the views with new data items when the original item is no longer visible.
The following code example shows a simple implementation for a data set that consists of an array of strings displayed using TextView
widgets:
class MyAdapter(private val myDataset: List<Item>,
private val mListener: OnListActivityInteractionListener) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val mOnClickListener: View.OnClickListener
init {
mOnClickListener = View.OnClickListener { v ->
val item = v.tag as Item
mListener.onListActivityInteraction(item)
}
}//view types
companion object {
const val HEADER = 1
const val CHILD = 2
}
// Return the size of your dataset (invoked by the layout manager)
override fun getItemCount() = myDataset.size
}
Item data class
data class Item(
val name: String,
val value: String
)
getItemViewType
override fun getItemViewType(position: Int): Int {
return when (myDataset[position].value) {
"HEADING" -> HEADER
else -> CHILD
}
}
onCreateViewHolder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view: View
when (viewType) {
HEADER -> {
view = LayoutInflater.from(parent.context)
.inflate(R.layout.header_item, parent, false)
return HeaderViewHolder(view)
}
CHILD -> {
view = LayoutInflater.from(parent.context)
.inflate(R.layout.child_item, parent, false)
return ChildViewHolder(view)
}
else -> {
view = LayoutInflater.from(parent.context)
.inflate(R.layout.empty, parent, false)
return HeaderViewHolder(view)
}
}
}
onBindViewHolder
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = myDataset[position]
when (getItemViewType(position)) {
HEADER -> (holder as HeaderViewHolder).textView.text = item.name
CHILD -> {
val viewHolder =
(holder as ChildViewHolder)
viewHolder.textView.text = item.name
with(viewHolder.mView) {
tag = item
setOnClickListener(mOnClickListener)
}
}
}
}
HeaderViewHolder & ChildViewHolder
inner class HeaderViewHolder(mView: View) : RecyclerView.ViewHolder(mView) {
val textView: AppCompatTextView = mView.tvTitle
}
inner class ChildViewHolder(val mView: View) : RecyclerView.ViewHolder(mView) {
val textView: AppCompatTextView = mView.tvName
}
Final result
I hope you have an idea of how to implement multiple view types in RecyclerView together with click listener. You can change views and do how you like.
If you enjoyed this article then smash the applause icon a couple of times for appreciation.