Android RecyclerView → Android RecyclerView – CardView with CheckBox,Images,Text and ItemClick – Camposha

Android RecyclerView

Android RecyclerView

Android RecyclerView

Android RecyclerView – CardView with CheckBox,Images,Text and ItemClick

Kotlin Android RecyclerView with CheckBoxes, Images, text and ItemClick supports Tutorial and Example.

I want to show you how you can work with the recyclerview in this tutorial and do common things like using it with checkboxes, images, textview and also supporting click events. All these we do in a single MainActivity.kt file.

 

Video Tutorial

If you prefer a video tutorial then check here:

What You Learn

Here are the concepts you learn:

  1. How to use Recyclerview in android with Kotlin Programming Language.
  2. How to use CheckBox with recyclerview and handle the checkbox states appropriately.
  3. How to create a recyclerview with images and text.
  4. How to support item click event in recyclerview.

Tools Used

Here are the tools I used for this project:

  1. Programming Language : Kotlin
  2. Framework – Android
  3. IDE – Android Studio.
  4. Emulator – Nox Player
  5. OS : Windows 8.1

Let’s start.

Demo

Here are the demo for this project:

Kotlin Android RecyclerView with CheckBox,Images and Text

Here’s the project in landscape mode.
Kotlin Android RecyclerView with CheckBox,Images and Text

(a). Build.gradle

Our app level build.gradle.
This is where we add our dependencies. Especially we are interested in three main of those:

  1. AppCompat – To give us the AppCompatActivity from which our MainActivity will derive.
  2. Design Support – To give us the RecyclerView.
  3. CardView – To give us Cardview.

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support:appcompat-v7:28.0.0-alpha3'
    implementation 'com.android.support:design:28.0.0-alpha3'
    implementation 'com.android.support:cardview-v7:28.0.0-alpha3'
}

(b). activity_main.xml

This is our main activity’s layout. Here are the components we use:

  1. RelativeLayout – To arrange our other widgets relative to each other.
  2. TextView – To render header text.
  3. RecyclerView – To render our data.
  4. Floating Action Button – To show the checked items when clicked.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    
    
    android_layout_width="match_parent"
    android_layout_height="match_parent"
    tools_context="com.devosha.kotlin_recyclerview_checkbox.MainActivity">

    <TextView
        android_id="@+id/headerTextView"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_text="Spiritual Teachers"
        android_textAlignment="center"
        android_textAppearance="@style/TextAppearance.AppCompat.Large"
        android_textColor="@color/colorAccent" />

    <android.support.v7.widget.RecyclerView
        android_id="@+id/myRecycler"
        class="android.support.v7.widget.RecyclerView"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_layout_alignParentLeft="true"
        android_layout_alignParentStart="true"
        android_layout_below="@+id/headerTextView"
        android_layout_marginTop="30dp" />

    <android.support.design.widget.FloatingActionButton
        android_id="@+id/fab"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_alignParentBottom="true"
        android_layout_alignParentEnd="true"
        android_layout_alignParentRight="true"
        android_layout_gravity="bottom|end"
        android_src="@android:drawable/ic_dialog_email" />

</RelativeLayout>

(c). model.xml

This layout will define our item views for our recyclerview, it will model them. Basically it will be rendering data for a single SpiritualTeacher object. At the root we have a CardView. Then we also have:

  1. ImageView – To render image for the SpiritualTeacher object.
  2. TextVIew – To render his name as well as description.
  3. CheckBox – To allow us select and unselect the CardViews.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView 
    android_orientation="horizontal" android_layout_width="match_parent"
    
    android_layout_margin="5dp"
    card_view_cardCornerRadius="10dp"
    card_view_cardElevation="5dp"
    android_layout_height="match_parent">

    <RelativeLayout
        android_layout_width="match_parent"
        android_layout_height="match_parent">
        <ImageView
            android_layout_width="150dp"
            android_layout_height="150dp"
            android_id="@+id/teacherImageView"
            android_padding="5dp"
            android_src="@drawable/cle" />

        <TextView
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_textAppearance="?android:attr/textAppearanceLarge"
            android_text="Teacher Name"
            android_id="@+id/nameTextView"
            android_padding="5dp"
            android_textColor="@color/colorAccent"
            android_layout_alignParentTop="true"
            android_layout_toRightOf="@+id/teacherImageView" />

        <TextView
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_textAppearance="?android:attr/textAppearanceMedium"
            android_text="Teacher Description..."
            android_id="@+id/descritionTextView"
            android_padding="5dp"
            android_layout_alignBottom="@+id/teacherImageView"
            android_layout_toRightOf="@+id/teacherImageView" />

        <CheckBox
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_id="@+id/myCheckBox"
            android_layout_alignParentRight="true"
            />

    </RelativeLayout>
</android.support.v7.widget.CardView>

(d). MainActivity.kt

This is our main activity. This is our only file and we will define several inner kotlin classes here. This class will be deriving from the AppCompatActivity.

Create Data Object

We will start by defining an inner class called SpiritualTeacher:

   inner class SpiritualTeacher(var name: String?, val quote: String, val image: Int) {
        var isSelected: Boolean = false
    }

That class is our data object. It will receive it’s parameters via the constructor. Moreover we are maintaining a simple boolean as you can see that will hold for us the selection state of the CardViews. In fact this is the magic to allow us select and unselect our items in our recyclerview. Thus our recyclerview will not lose the state even as we scroll and the recyclerview items get recycled. This is because we are holding them as data in our object and they are not affected by the recycling.

Create RecyclerVew Adapter class

Normally the Adapter has two main roles. First to inflate our custom layouts and secondly to bind data to the resultant widgets. However recyclerview always goes further by allowing us to recycle items. This saves memory consumption as inflation is an expensive process and would impact negatively on our app if we were to do it for every item in the recyclerview.

So we will create an adapter:

    internal class MyAdapter(var c: Context, var teachers: Array<SpiritualTeacher>) : RecyclerView.Adapter<MyAdapter.MyHolder>() {..}

We’ve made it derive from the RecyclerView.Adapter class.

Inside the adapter first we will create an arraylist that will hold for us the teachers that have been checked:

        var checkedTeachers = ArrayList<SpiritualTeacher>()

It is inside the onCreateViewHolder() method where we will be inflating our model.xml into a View object. For that we use the LayoutInflater class.

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
            val v = LayoutInflater.from(parent.context).inflate(R.layout.model, null)
            return MyHolder(v)
        }

Here’s the full source code.

package com.devosha.kotlin_recyclerview_checkbox
import android.content.Context
import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import java.util.ArrayList
/**
* class: MainActivity
* This class is deriving from `android.support.v7.app.AppCompatActivity`.
*/
class MainActivity : AppCompatActivity() {
private val teachers: Array<SpiritualTeacher>
get() =
arrayOf(SpiritualTeacher("Rumi", "Out beyond ideas of wrongdoing and rightdoing there is a field.I'll meet you there.", R.drawable.rumi),
SpiritualTeacher("Anthony De Mello", "Don't Carry Over Experiences from the past", R.drawable.anthony_de_mello),
SpiritualTeacher("Eckhart Tolle", "Walk as if you are kissing the Earth with your feet.", R.drawable.eckhart_tolle),
SpiritualTeacher("Meister Eckhart", "Man suffers only because he takes seriously what the gods made for fun.", R.drawable.meister_eckhart),
SpiritualTeacher("Mooji", "I have lived with several Zen masters -- all of them cats.", R.drawable.mooji),
SpiritualTeacher("Confucius", "I'm simply saying that there is a way to be sane. I'm saying that you ", R.drawable.confucius),
SpiritualTeacher("Francis Lucille", "The way out is through the door. Why is it that no one will use this method?", R.drawable.francis_lucille),
SpiritualTeacher("Thich Nhat Hanh", "t is the power of the mind to be unconquerable.", R.drawable.thich),
SpiritualTeacher("Dalai Lama", "It's like you took a bottle of ink and you threw it at a wall. Smash! ", R.drawable.dalai_lama),
SpiritualTeacher("Jiddu Krishnamurti", "A student, filled with emotion and crying, implored, 'Why is there so much suffering?", R.drawable.jiddu_krishnamurti),
SpiritualTeacher("Osho", "Only the hand that erases can write the true thing.", R.drawable.osho),
SpiritualTeacher("Sedata", "Many have died; you also will die. The drum of death is being beaten.", R.drawable.sedata),
SpiritualTeacher("Allan Watts", "Where there are humans, You'll find flies,And Buddhas.", R.drawable.allant_watts),
SpiritualTeacher("Leo Gura", "Silence is the language of Om. We need silence to be able to reach our Self.", R.drawable.sadhguru),
SpiritualTeacher("Rupert Spira", "One day in my shoes and a day for me in your shoes, the beauty of travel lies ", R.drawable.rupert_spira),
SpiritualTeacher("Sadhguru", "Like vanishing dew,a passing apparition or the sudden flashnof lightning", R.drawable.sadhguru))
internal var sb: StringBuilder? = null
internal lateinit var adapter: MyAdapter
inner class SpiritualTeacher(var name: String?, val quote: String, val image: Int) {
var isSelected: Boolean = false
}
internal class MyAdapter(var c: Context, var teachers: Array<SpiritualTeacher>) : RecyclerView.Adapter<MyAdapter.MyHolder>() {
var checkedTeachers = ArrayList<SpiritualTeacher>()
//VIEWHOLDER IS INITIALIZED
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.model, null)
return MyHolder(v)
}
//DATA IS BOUND TO VIEWS
override fun onBindViewHolder(holder: MyHolder, position: Int) {
val teacher = teachers[position]
holder.nameTxt.text = teacher.name
holder.posTxt.text = teacher.quote
holder.myCheckBox.isChecked = teacher.isSelected
holder.img.setImageResource(teacher.image)
holder.setItemClickListener(object : MyHolder.ItemClickListener {
override fun onItemClick(v: View, pos: Int) {
val myCheckBox = v as CheckBox
val currentTeacher = teachers[pos]
if (myCheckBox.isChecked) {
currentTeacher.isSelected = true
checkedTeachers.add(currentTeacher)
} else if (!myCheckBox.isChecked) {
currentTeacher.isSelected = false
checkedTeachers.remove(currentTeacher)
}
}
})
}
override fun getItemCount(): Int {
return teachers.size
}
internal class MyHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
var img: ImageView
var nameTxt: TextView
var posTxt: TextView
var myCheckBox: CheckBox
lateinit var myItemClickListener: ItemClickListener
init {
nameTxt = itemView.findViewById(R.id.nameTextView)
posTxt = itemView.findViewById(R.id.descritionTextView)
img = itemView.findViewById(R.id.teacherImageView)
myCheckBox = itemView.findViewById(R.id.myCheckBox)
myCheckBox.setOnClickListener(this)
}
fun setItemClickListener(ic: ItemClickListener) {
this.myItemClickListener = ic
}
override fun onClick(v: View) {
this.myItemClickListener.onItemClick(v, layoutPosition)
}
internal interface ItemClickListener {
fun onItemClick(v: View, pos: Int)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
adapter = MyAdapter(this, teachers)
val fab = findViewById(R.id.fab) as FloatingActionButton
fab.setOnClickListener {
sb = StringBuilder()
var i = 0
while (i < adapter.checkedTeachers.size) {
val spiritualTeacher = adapter.checkedTeachers[i]
sb!!.append(spiritualTeacher.name)
if (i != adapter.checkedTeachers.size - 1) {
sb!!.append("n")
}
i++
} 
if (adapter.checkedTeachers.size > 0) {
Toast.makeText([email protected], sb!!.toString(), Toast.LENGTH_SHORT).show()
} else {
Toast.makeText([email protected], "Please Check An Item First", Toast.LENGTH_SHORT).show()
}
}
//RECYCLER
val rv = findViewById(R.id.myRecycler) as RecyclerView
rv.layoutManager = LinearLayoutManager(this)
rv.itemAnimator = DefaultItemAnimator()
//SET ADAPTER
rv.adapter = adapter
}
// end
}

Leave a Reply

Your email address will not be published. Required fields are marked *

Join Us
X