When developing an App, it is often we need to display various lists. We can easily implement various lists with Android’s RecyclerView.
The complete code can be found in .
Table of Contents
Creating a Project
Create a new Basic Activity project. The Basic Activity project presets MainActivity, FirstFragment, and SecondFragment. We will implement a list in FirstFragment. Therefore, MainActivity and SecondFragment will not be modified.
Creating View and Data for Each Row
Suppose that in each row in the list, there are only two TextViews, one for Key and one for Value. Under res/layout/, add row.xml with the following content:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/keyTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/valueTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
Next, we create a data class for the data required by each row. Add RowData, the code is as follows:
package com.waynestalk.androidrecyclerviewexample data class RowData(val key: String, val value: String)
RecyclerView.Adapter
When RecyclerView is drawing a list, RecyclerView.Adapter is used to provide a view for each row. RecyclerView just draws received views one by one.
Add FirstAdapter, the code is as follows:
import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.RecyclerView class FirstAdapter(private val dataset: Array<RowData>) : RecyclerView.Adapter<FirstAdapter.ViewHolder>() { inner class ViewHolder(listItemView: View) : RecyclerView.ViewHolder(listItemView) { val keyTextView = itemView.findViewById<TextView>(R.id.keyTextView) val valueTextView = itemView.findViewById<TextView>(R.id.valueTextView) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val inflater = LayoutInflater.from(parent.context) val view = inflater.inflate(R.layout.row, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val rowData = dataset[position] holder.keyTextView.text = rowData.key holder.valueTextView.text = rowData.value } override fun getItemCount(): Int { return dataset.size } }
The view of a row will be contained in a ViewHolder. So, in FirstAdapter, we declare a ViewHolder inheriting RecylerView.ViewHolder, and parameter listItemView
of the constructor is the row view. This listItemView
will be set to RecyclerView.ViewHolder.itemView
. Then, in the constructor, we will take out the references of all the sub-views in the row.
inner class ViewHolder(listItemView: View) : RecyclerView.ViewHolder(listItemView) { val keyTextView = itemView.findViewById<TextView>(R.id.keyTextView) val valueTextView = itemView.findViewById<TextView>(R.id.valueTextView) }
We pass all the data to the constructor of FirstAdapter. After inheriting RecyclerView.Adapter, FirstAdapter must implement three methods:
getItemCount()
: The total number of rows in the list.onCreateViewHolder()
: We will to initiate a row view in this method here.onBindViewHolder()
: we will set row data to row view here.
In this way, we have all prepared code for the row part.
RecyclerView
Next, we start to use RecyclerView to draw the list. First of all, first modify fragment_first.xml, we put in <RecyclerView>.
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".FirstFragment"> <Button android:id="@+id/button_first" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/next" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/button_first" /> </androidx.constraintlayout.widget.ConstraintLayout>
Add FirstViewModel to provide RowData.
package com.waynestalk.androidrecyclerviewexample import androidx.lifecycle.ViewModel class FirstViewModel : ViewModel() { val dataset = arrayOf( RowData("Side name", "Wayne's Talk"), RowData("URL", "https://waynestalk.com"), ) }
In FirstFragment, we must create FirstAdapter and pass RowData to it. Then, set FirstAdapter to RecyclerView.
package com.waynestalk.androidrecyclerviewexample import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView class FirstFragment : Fragment() { private lateinit var viewModel: FirstViewModel override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { viewModel = ViewModelProvider(this).get(FirstViewModel::class.java) val root = inflater.inflate(R.layout.fragment_first, container, false) val recyclerView = root.findViewById<RecyclerView>(R.id.recyclerView) recyclerView.adapter = FirstAdapter(viewModel.dataset) recyclerView.layoutManager = LinearLayoutManager(activity) return root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) view.findViewById<Button>(R.id.button_first).setOnClickListener { findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment) } } }
Conclusion
Is RecyclerView simple? It helps us draw a list row by row, and we only need to consider how to draw each row. So, most of the logic is in FirstAdapter, it is much simpler!