Recyclerview Card Item Onclick Kotlin - android

I want to create a new intent/activity when the user clicks on a cardview respectively and i was wondering how does one do it in kotlin. i noticed most tutorials are in java and i'm a student who did not learn java.
package com.example.ttshfypj.adapters
import androidx.fragment.app.Fragment
import android.view.View
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.ttshfypj.data_class.medications
import android.widget.ImageView
import android.widget.TextView
import com.example.ttshfypj.R
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.list_medication.view.*
class medicationAdapter (val medicationlist: ArrayList<medications>) : RecyclerView.Adapter<medicationAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.list_medication, parent, false)
return ViewHolder(v)
}
override fun getItemCount(): Int {
return medicationlist.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val medicationgroup: medications = medicationlist[position]
holder?.medicationnamevar?.text = medicationgroup.medicineN
holder?.medicationschedulevar?.text = medicationgroup.MedicineTime
val imagemedicine = holder?.itemView?.medicationimageview
Picasso.get().load(medicationgroup.MedicineImage).into(imagemedicine)
}
class ViewHolder(itemView: View) :RecyclerView.ViewHolder(itemView) {
val medicationnamevar = itemView.findViewById(R.id.medicationname) as TextView
val medicationschedulevar = itemView.findViewById(R.id.medicationschedule) as TextView
}
}

If you are using kotlin you can also use method reference where you directly pass a method to be called inside the adapter and you can directly invoke it there.
Activity.kt
Adapter(this::itemClickHandler);
private fun itemClickHandler(int position){
// your logic here
}
Adapter.kt
class Adapater(val itemClickHandler:(Int)->Unit):RecyclerView.Adapter(){
override fun onBindViewHolder(){
//you can invoke it here like this
itemClickHandler.invoke(adapterPosition);
}
}
please refer this full code
MainActivity.kt
package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val list = mutableListOf<Items>()
for(i in 1..25){
list.add(Items(CHILD,"Child"))
}
with(rvList) {
layoutManager = LinearLayoutManager(this#MainActivity)
adapter = Adapter(list, this#MainActivity::onItemClickHandler)
}
}
private fun onItemClickHandler(position:Int){
Log.d("***","${position}");
//here you can start a new intent to open a new activity on click of item
}
}
The adapter code is as following
package com.example.myapplication
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.layout_child.view.*
import kotlinx.android.synthetic.main.layout_header.view.*
const val HEADER = 1;
const val CHILD = 2;
data class Items(val type: Int, val text: String)
class Adapter(private val list: List<Items>, val itemClickHandler: (Int) -> Unit) :
RecyclerView.Adapter<Adapter.HeaderViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HeaderViewHolder {
val headerView =
LayoutInflater.from(parent.context).inflate(R.layout.layout_header, parent, false)
val headerViewHolder = HeaderViewHolder(headerView)
headerView.setOnClickListener {
itemClickHandler.invoke(headerViewHolder.adapterPosition)
}
return headerViewHolder
}
override fun getItemCount(): Int = list.size
override fun onBindViewHolder(holder: HeaderViewHolder, position: Int) {
holder.onBind(list[position].text)
}
inner class HeaderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun onBind(text: String) {
itemView.tvHeader.text = text
}
}
}
Hope this helps and you are able to follow

You can create an interface for Item Click Listener like
interface MyItemClickListener{
fun itemClick(position: Int)
}
Now you should pass context to the constructor of your adapter.
class medicationAdapter (val medicationlist: ArrayList<medications>, var context: Context) : RecyclerView.Adapter<medicationAdapter.ViewHolder>() {...}
and create an instance of MyItemClickListener inside your adapter
// create instance of MyItemClickListener
private val clickListener = context as MyItemClickListener
And setclick listener on your view inside the onCreateViewHolder.
modify your adapter like this
class medicationAdapter (val medicationlist: ArrayList<medications>, var context: Context) : RecyclerView.Adapter<medicationAdapter.ViewHolder>() {
// create instance of MyItemClickListener
private val clickListener = context as MyItemClickListener
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
var inflater = LayoutInflater.from(parent.context)
var v = inflater.inflate(R.layout.list_medication, parent, false)
var viewHolder = ViewHolder(v)
// here you set click listener on your item view.
v.setOnClickListener {
clickListener.itemClick(viewHolder.adapterPosition)
}
return viewHolder
}
override fun getItemCount(): Int {
return medicationlist.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val medicationgroup: medications = medicationlist[position]
holder?.medicationnamevar?.text = medicationgroup.medicineN
holder?.medicationschedulevar?.text = medicationgroup.MedicineTime
val imagemedicine = holder?.itemView?.medicationimageview
Picasso.get().load(medicationgroup.MedicineImage).into(imagemedicine)
}
class ViewHolder(itemView: View) :RecyclerView.ViewHolder(itemView) {
val medicationnamevar = itemView.findViewById(R.id.medicationname) as TextView
val medicationschedulevar = itemView.findViewById(R.id.medicationschedule) as TextView
}
}
And finally, in your activity, you have to implement the MyItemClickListener interface and override the itemClick() like this
class YourActivity: AppCompatActivity(), MyItemClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// ....
}
override fun itemClick(position: Int) {
Log.d("TAG","Click Item Position: "+position)
// here you can call your new activity according to your item position.
}
}

Related

Error when setting button inside recycler view?

I get error when I press button inside recycler view. My application is not crashing. I am trying to set a button in the recycler view and callingsetOnClickListener inside onBindViewHolder. Inside the holder.Button.setOnClickListener{}I change the button text to notified. But when I press a button the values of other button text in another list also changes. This is a listview of firestore documents. I have many documents that are uploaded into the recycler view. If I am getting the error how should I implement the button onclicklistener without this error.[![https://i.stack.imgur.com/S0Oxm.jpg][1]][1] [![enter image description here][2]][2]
/**This my activity for recycler view*/
package com.example.bloodbankcompany.recyclerview
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Adapter
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.bloodbankcompany.MyAdapter
import com.example.bloodbankcompany.R
import com.example.bloodbankcompany.User1
import com.example.bloodbankcompany.User2
import com.google.firebase.firestore.*
import java.lang.NullPointerException
class MainActivity2 : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var userArrayList: ArrayList<User2>
private lateinit var myAdapter: MyAdapter2
private val mFireStore = FirebaseFirestore.getInstance()
var db = FirebaseFirestore.getInstance()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
recyclerView= findViewById(R.id.recyclerview)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.setHasFixedSize(true)
userArrayList= arrayListOf()
myAdapter =MyAdapter2(userArrayList)
recyclerView.adapter = myAdapter
EventChangeListener()
}
private fun EventChangeListener() {
try {
mFireStore.collection("applicationForm").addSnapshotListener(object :
EventListener<QuerySnapshot> {
override fun onEvent(value: QuerySnapshot?, error: FirebaseFirestoreException?) {
if (error != null) {
Log.e("firestore error", error.message.toString())
}
try {
for (dc: DocumentChange in value?.documentChanges!!) {
if (dc.type == DocumentChange.Type.ADDED) {
userArrayList.add(dc.document.toObject(User2::class.java))
}
// Toast.makeText(applicationContext,userArrayList.toString(), Toast.LENGTH_SHORT).show()
}
} catch (e:NullPointerException){
}
myAdapter.notifyDataSetChanged()
}
})
} catch (e:NullPointerException){
}
}
}
/**
* This is my myAdapter activity for adapater*/
package com.example.bloodbankcompany.recyclerview
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.example.bloodbankcompany.R
import com.example.bloodbankcompany.RegisterActivity
import com.example.bloodbankcompany.User2
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.android.synthetic.main.list_item2.view.*
class MyAdapter2(private val userList: ArrayList<User2>): RecyclerView.Adapter<MyAdapter2.MyViewHolder>(){
var id: String = ""
private val mFireStore = FirebaseFirestore.getInstance()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyAdapter2.MyViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.list_item2,parent,false)
return MyViewHolder(itemView)
}
override fun onBindViewHolder(holder: MyAdapter2.MyViewHolder, position: Int) {
val user:User2 = userList[position]
holder.name.text= user.name
holder.phone.text= user.phone
holder.address.text =user.address
holder.bloodGroup.text= user.bloodgroup
holder.id.text = user.id
//Setting onclicklistener to my adapter and starting intent
holder.button.setOnClickListener {
// holder.io = "kkj"
// holder.id.text = " "
holder.button.setText("notified")
// val context=holder.button.context
// val intent = Intent( context, RegisterActivity::class.java)
// context.startActivity(intent)
}
}
override fun getItemCount(): Int {
return userList.size
}
public class MyViewHolder(itemView : View): RecyclerView.ViewHolder(itemView){
val name : TextView = itemView.findViewById(R.id.tvfirstname1)
val phone :TextView= itemView.findViewById(R.id.tvphone11)
val address : TextView= itemView.findViewById(R.id.tvaddress1)
val bloodGroup: TextView =itemView.findViewById(R.id.tvbloodg1)
val id: TextView = itemView.findViewById(R.id.tvid)
var io: String? = ""
var button: Button = itemView.findViewById(R.id.btn_notify)
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
init {
itemView.btn_notify.setOnClickListener {
}
}
}
}
} ```
[1]: https://i.stack.imgur.com/S0Oxm.jpg
[2]: https://i.stack.imgur.com/BqDMf.jpg
create interface for clickListener in your adapter and set it in constructor
interface OnItemClickListener {
fun onItemClick(position: Int)
}
and in ViewHolder set bind your button
fun bind(position: Int, listener: OnItemClickListener) {
button.setOnClickListener { v -> listener.onItemClick(position) }
}
and then set this code in onBindViewHolder
holder.bind( position , onItemClickListener)
finally when click on button you can action in Activity or Fragment
example :
adapter = Adapter(getContext(), models) { position -> }
Simple Code, Without using Interface
Actually what I found is you were doing it the correct way, but you were using two ViewHolder classes there which is the cause of issue. Try to use the below code once and try again. Hope it works.
class mAdapter(val context: Context, private val dataList: ArrayList<String>):
RecyclerView.Adapter<mAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): mAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.item_card_view, parent, false)
return mAdapter.ViewHolder(v)
}
override fun onBindViewHolder(holder: mAdapter.ViewHolder, position: Int) {
holder.txtView.setText(dataList.get(position))
//Your Button setOnClickLister
holder.btnName.setOnClickListener {
// action here
}
}
override fun getItemCount(): Int {
return dataList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val txtView = itemView.findViewById(R.id.textView) as TextView
val btnName = itemView.findViewById(R.id.btnName) as Button
}
}

RecyclerView , kotlin, click response delay

Peace
i have made simple recyclerview, with interface clickListener
consisting of 4 items showing toast on click.
It works fine if i single click per second,
but if i Rapidly click on different items ( 2 or 3 times in 1 seconds )
it still shows the toast each second,
not rapidly changing the toast
data class code:
package com.elsersy.rv5
data class Items (var textt:String) {
}
adapter code
package com.elsersy.rv5
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
class MyAdapter(private var stringList:ArrayList<Items>,private val listener:MyOnClickListener):
RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
inner class MyViewHolder(itemView:View):RecyclerView.ViewHolder(itemView) {
var text:TextView = itemView.findViewById(R.id.textView)
init {
itemView.setOnClickListener {
val position = absoluteAdapterPosition
if (position != RecyclerView.NO_POSITION)
{
listener.onItemClick(position)
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.row_item,parent,false)
return MyViewHolder(itemView)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem = stringList[position]
holder.text.text = currentItem.textt
}
override fun getItemCount(): Int {
return stringList.size
}
interface MyOnClickListener{
fun onItemClick(position: Int)
}
fun setData(newItemList:ArrayList<Items>){
val diffUtil = MyDiffUtil(stringList,newItemList)
val diffResults = DiffUtil.calculateDiff(diffUtil)
stringList = newItemList
diffResults.dispatchUpdatesTo(this)
}
}
ActivityMainCode
package com.elsersy.rv5
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import com.elsersy.rv5.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity(),MyAdapter.MyOnClickListener {
private lateinit var binding: ActivityMainBinding
private lateinit var stringList:ArrayList<Items>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.recyclerView.layoutManager = LinearLayoutManager(this)
stringList = arrayListOf<Items>()
getStrings()
binding.recyclerView.adapter=MyAdapter(stringList,this)
}
private fun getStrings() {
for (a in 0..4){
var string_Array = resources.getStringArray(R.array.string_array)
stringList.add(Items(string_Array[a]))
}
}
override fun onItemClick(position: Int) {
Toast.makeText(this,"$position is clicked", Toast.LENGTH_SHORT).show()
}
}
If you want to cancel the previous toast before showing a new one, assign it as a member variable and cancel it before showing the new one:
private var toast : Toast? = null
..
override fun onItemClick(position: Int) {
toast?.cancel()
toast = Toast.makeText(this,"$position is clicked", Toast.LENGTH_SHORT)
toast?.show()
}

Android: pass data from RecyclerView to another Activity

I have a RecyclerView and I have to pass data to another activity when u click on an item. When someone clicks on the first item I need to pass the data of that item to an activity.
This is the part of the fragment where the recycler view is located:
class TrafficFragment : Fragment() {
private lateinit var trafficViewModel: TrafficViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
trafficViewModel =
ViewModelProviders.of(this).get(TrafficViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_traffic, container, false)
//...
val recyclerViewTraffic: RecyclerView = root.findViewById(R.id.recyclerViewTraffic)
recyclerViewTraffic.apply {
layoutManager = LinearLayoutManager (this#TrafficFragment.context)
Log.d("DEBUG", MainActivity.clickArray.toString())
adapter = TrafficAdapter(MainActivity.clickArray){
var intent = Intent(activity, ClickDetail::class.java)
startActivity(intent)
}
}
return root
}
}
The adapter:
package com.example.example
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.traffic_recycler_layout.view.*
class TrafficAdapter(private val trafficClick: List<TrafficClick>, val clickDetail: () -> Unit) :
RecyclerView.Adapter<TrafficAdapter.ViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutView = LayoutInflater.from(parent.context).inflate(R.layout.traffic_recycler_layout, parent, false)
return ViewHolder(layoutView)
}
override fun getItemCount(): Int = MainActivity.clicksNumber
companion object{
var idClick: String?= String()
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val clicks = trafficClick[position]
holder.view.indirizzoIp.text = "${clicks.ip}"
holder.view.isp.text= "${clicks.organization}"
holder.view.data.text = "${clicks.data_creation}"
holder.view.numberText.text = "${clicks.id_campaign}"
holder.view.setOnClickListener {
clickDetail.invoke()
}
}
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view)
}
and this is the activity that I need to open when I click on the item with the details of that item:
package com.example.example
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.traffic_click_detail.*
class ClickDetail : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.traffic_click_detail)
}
}
var intent = Intent(activity, ClickDetail::class.java)
intent.putExtra("your_key",MainActivity.clickArray.toString())
startActivity(intent)
class ClickDetail : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.traffic_click_detail)
val YourData = getIntent().getStringExtra("your_key")
}
}
If I suppose you want to pass and id, replace this
holder.view.setOnClickListener {
clickDetail.invoke()
}
by
holder.view.setOnClickListener {
ClickDetail.launch(holder.itemView.context, /*your ID*/)
}
Then to retrieve your data
class ClickDetail : AppCompatActivity(){
companion object {
private const val EXTRA_KEY_ID = "CLICKDETAIL.EXTRA_KEY_ID"
fun launch(launcher: Activity, id: Int) {
val intent = Intent(launcher, ClickDetail::class.java)
.apply {
putExtra(EXTRA_KEY_ID, id)
}
launcher.startActivity(intent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.traffic_click_detail)
val id = intent.getIntExtra("EXTRA_KEY_ID")
}
}

Onclick listeners on views in recycler view row

I have a recycler view made up for rows. Each row has a button and an image. I want to add an onClick listener on each image. How can I do that using android and kotlin? I know how to add an onClick listener on the row but not on the elements of the row?
Here's my code
import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.squareup.picasso.Picasso
import com.sumizeit.sumizeit.*
import kotlinx.android.synthetic.main.activity_home.*
class HomeAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder> {
private var context: Context
private var list: ArrayList<HomeRow>
constructor(context: Context, list: ArrayList<HomeRow>){
this.context = context
this.list = list
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val vHolder = holder as YourViewHolder
Picasso.get().load(list[position].image1).into(vHolder.txtImage1);
Picasso.get().load(list[position].image2).into(vHolder.txtImage2);
Picasso.get().load(list[position].image3).into(vHolder.txtImage3);
Picasso.get().load(list[position].image4).into(vHolder.txtImage4);
Picasso.get().load(list[position].image5).into(vHolder.txtImage5);
vHolder.txtImage1.setOnClickListener {
//TODO something..
Intent(context, BookDetailActivity::class.java).apply {
putExtra("bookId", list[position].id1)
}
}
vHolder.txtImage2.setOnClickListener {
//TODO something..
Intent(context, BookDetailActivity::class.java).apply {
putExtra("bookId", list[position].id2)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.home_row, parent, false)
return YourViewHolder(view)
}
override fun getItemCount(): Int {
return list.size
}
var onItemClick: ((pos: Int, view: View) -> Unit)? = null
inner class YourViewHolder(itemView: View): RecyclerView.ViewHolder(itemView), View.OnClickListener {
override fun onClick(v: View) {
onItemClick?.invoke(adapterPosition, v)
}
val txtImage1 = itemView.findViewById<ImageView>(R.id.imageView1)
val txtImage2 = itemView.findViewById<ImageView>(R.id.imageView2)
val txtImage3 = itemView.findViewById<ImageView>(R.id.imageView3)
val txtImage4 = itemView.findViewById<ImageView>(R.id.imageView4)
val txtImage5 = itemView.findViewById<ImageView>(R.id.imageView5)
init {
itemView.setOnClickListener(this)
}
}
}
in Activity
var adp = HomeAdapter(this, listHomeRow);
rv.adapter = adp
change your code
override fun onClick(v: View) {
onItemClick?.invoke(adapterPosition, v)
}
val txtImage1 = itemView.findViewById<ImageView>(R.id.imageView1)
val txtImage2 = itemView.findViewById<ImageView>(R.id.imageView2)
val txtImage3 = itemView.findViewById<ImageView>(R.id.imageView3)
val txtImage4 = itemView.findViewById<ImageView>(R.id.imageView4)
val txtImage5 = itemView.findViewById<ImageView>(R.id.imageView5)
init {
itemView.setOnClickListener(this)
}
}
to
inner class YourViewHolder(itemView: View): RecyclerView.ViewHolder(itemView), View.OnClickListener {
override fun onClick(v: View) {
onItemClick?.invoke(adapterPosition, v)
}
val txtImage1 = itemView.findViewById<ImageView>(R.id.imageView1)
val txtImage2 = itemView.findViewById<ImageView>(R.id.imageView2)
val txtImage3 = itemView.findViewById<ImageView>(R.id.imageView3)
val txtImage4 = itemView.findViewById<ImageView>(R.id.imageView4)
val txtImage5 = itemView.findViewById<ImageView>(R.id.imageView5)
init {
txtImage1.setOnClickListener{
Intent(context, BookDetailActivity::class.java).apply {
putExtra("bookId", list[layoutPosition].id1)
context.startActivity(this)
}
}
txtImage2.setOnClickListener{
Intent(context, BookDetailActivity::class.java).apply {
putExtra("bookId", list[layoutPosition].id2)
context.startActivity(this)
}
}
}
}
and remove clickListener in your bindViewHolder() method. try this bro.
In anticipation of your adapter, I made some sample code.
class CategoryAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder> {
private var context: Context
private var list: ArrayList<YourItem>
constructor(context: Context, list: ArrayList<YourItem>){
this.context = context
this.list = list
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.your_layout, parent, false)
YourViewHolder(view)
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val cameraViewHolder = holder as YourViewHolder
cameraViewHolder.imageView.setOnClickListener {
//TODO something..
Intent(context, MainActivity::class.java).apply {
putExtra("category", list[position].name)
}
}
}
internal class YourViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.your_image
}
}
New, Try this
import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.squareup.picasso.Picasso
import com.sumizeit.sumizeit.*
import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.android.synthetic.main.home_row.*
class HomeAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder> {
private var context: Context
private var list: ArrayList<HomeRow>
constructor(context: Context, list: ArrayList<HomeRow>){
this.context = context
this.list = list
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val vHolder = holder as YourViewHolder
with(Picasso.get()){
load(list[position].image1).into(vHolder.txtImage1)
load(list[position].image2).into(vHolder.txtImage2)
load(list[position].image3).into(vHolder.txtImage3)
load(list[position].image4).into(vHolder.txtImage4)
load(list[position].image5).into(vHolder.txtImage5)
}
vHolder.txtImage1.setOnClickListener {
//TODO something..
Intent(context, BookDetailActivity::class.java).apply {
putExtra("bookId", list[position].id1)
context.startActivity(this)
}
}
vHolder.txtImage2.setOnClickListener {
//TODO something..
Intent(context, BookDetailActivity::class.java).apply {
putExtra("bookId", list[position].id2)
context.startActivity(this)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.home_row, parent, false)
return YourViewHolder(view)
}
override fun getItemCount(): Int {
return list.size
}
inner class YourViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
val txtImage1 = itemView.imageView1
val txtImage2 = itemView.imageView2
val txtImage3 = itemView.imageView3
val txtImage4 = itemView.imageView4
val txtImage5 = itemView.imageView5
}
}
Inside the adapter where the ImageView is bound. Just use that reference to set the onClickListener. You're probably doing it inside the onBindViewHolder method or inside the ViewHolder.
Create a Custom view for the recycler view :
<androidx.cardview.widget.CardView
android:id="#+id/info_card_view"
app:cardCornerRadius="#dimen/dimen_card_radius"
app:cardElevation="#dimen/dimen_card_elevation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/dimen_common_margin">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/list_item_constraintlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/dimen_card_padding">
...
<!--Image corresponding to info-->
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/image_pexel"
android:layout_width="#dimen/dimen_0"
android:layout_height="wrap_content"
android:contentDescription="#null"
android:layout_margin="#dimen/dimen_common_margin"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:imageUrl="#{pexelPhoto.src.medium}"
app:layout_constraintEnd_toEndOf="parent"
tools:srcCompat="#drawable/ic_launcher_foreground"/>
...
</androidx.constraintlayout.widget.ConstraintLayout>
Create a custom viewholder which will have click listener for the image in recyclerview row :
class PhotosViewHolder(private val viewBinding: ViewDataBinding) :
RecyclerView.ViewHolder(viewBinding.root) {
fun bind(data: Any, listener: OnItemClickListener) {
viewBinding.setVariable(BR.pexelPhoto, data)
(viewBinding.root.findViewById(R.id.image_pexel) as ImageView).setOnClickListener { _ ->
listener.onThumbnailClick(data as PexelPhoto)
}
viewBinding.executePendingBindings()
}
}
You can check the complete source here for reference : https://github.com/spartan-1/PexelsApp

How to implement clicklistener on customadpter item in kotlin?

I want to implement onClickListener on recyclerview item. Here is my CustomAdapter.kt Code.
package com.png.kotlinsample
/**
* Created by admin on 13-08-2017.
*/
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
/**
* Created by prashant on 6/19/2017.
*/
class CustomAdapter(val userList: ArrayList<User>, val listener: (User) -> Unit) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
//this method is returning the view for each item in the list
class MyAdapter(val userList: ArrayList<User>)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.row_layout, parent, false)
return ViewHolder(v)
}
//this method is binding the data on the list
override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
holder.bindItems(userList[position],listener)
}
//this method is giving the size of the list
override fun getItemCount(): Int {
return userList.size
}
//the class is hodling the list view
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(user: User, listener: (User) -> Unit) = with(itemView) {
val textViewName = itemView.findViewById(R.id.textViewUsername) as TextView
val textViewAddress = itemView.findViewById(R.id.textViewAddress) as TextView
textViewName.text = user.name
textViewAddress.text = user.address
setOnClickListener { listener(user) }
}
}
}
I want the click listener callback from my activity.
class CustomAdapter(
val userList: List<User>,
val listener: (User) -> Unit
) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder = ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.row_layout, parent, false))
override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
holder.bindItems(userList[position])
}
override fun getItemCount(): Int = userList.size
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val textViewName: TextView = itemView.findViewById(R.id.textViewUsername)
private val textViewAddress: TextView = itemView.findViewById(R.id.textViewAddress)
fun bindItems(user: User) = with(itemView) {
textViewName.text = user.name
textViewAddress.text = user.address
setOnClickListener { listener(user) }
}
}
}
Then
val adapter = CustomAdapter(userList) { user ->
// do something with user on click
}
recyclerView.adapter = adapter
Ok let's do it in 3 steps
1- You define a interface with onClick method to be your callbacks
like this
interface UserClickCallbacks {
fun onUserClick(user: User)
}
2- Second in your adapter you add a click listener in the view holder with call the interface method like this
EDIT
class CustomAdapter(val userList: ArrayList<User>, private val userClickCallbacks: UserClickCallbacks) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
//this method is returning the view for each item in the list
class MyAdapter(val userList: ArrayList<User>)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.row_layout, parent, false)
return ViewHolder(v)
}
//this method is binding the data on the list
override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
holder.textViewName.text = user.name
holder.textViewAddress.text = user.address
}
//this method is giving the size of the list
override fun getItemCount(): Int {
return userList.size
}
//the class is hodling the list view
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
init {
view.setOnClickListener(this)
}
val textViewName = itemView.findViewById(R.id.textViewUsername)
val textViewAddress = itemView.findViewById(R.id.textViewAddress)
override fun onClick(p0: View?) {
userClickCallbacks.onUserClick(userList[adapterPosition])
}
}
}
3- At your activity you implement the the UserClickCallbacks interface
and override the onUserClick() method like this
class UserActivity : AppCompatActivity(), UserClickCallbacks {
// your activity code
override fun onUserClick(user: User) {
// but the user click event logic here
// This triggered when user in tha adapter clicked
}
}
Don't forget to add inner to ViewHolder class or else you won't get access to listener object which is inside Adapter :
package com.niel.customview
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
/**
* Created by nileshdeokar on 12/03/2018.
*/
class MediaAdapter(private var mData: ArrayList<String>) : RecyclerView.Adapter<MediaAdapter.ViewHolder>() {
lateinit var listener: OnItemClickedListener
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent?.context)
.inflate(R.layout.row_media, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
val model = mData[position]
}
override fun getItemCount(): Int {
return mData.size
}
inner class ViewHolder : RecyclerView.ViewHolder, View.OnClickListener {
var imageViewSq: ImageView
constructor(itemView: View?) : super(itemView) {
imageViewSq = itemView?.findViewById(R.id.imgSq)!!
itemView.setOnClickListener(this)
}
override fun onClick(p0: View?) {
listener.onItemClick(adapterPosition)
}
}
fun setOnItemClickedListener(listener: OnItemClickedListener) {
this.listener = listener
}
interface OnItemClickedListener {
fun onItemClick(position: Int)
}
}

Categories

Resources