Mehul Kanzariya
Mehul Kanzariya

Reputation: 1348

Item Onclick RecyclerView Kotlin Android

I have RecyclerView adapter in Kotlin and when a user clicks on categoryPhoto, I want to open a new activity. How should I implement this?

class CategoryAdapter(private val categoryList: List<Category>, private val context: Context) : RecyclerView.Adapter<CategoryAdapter.MyViewHolder>() {

class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        var categoryName = view.text_view_category_name
        var categoryPhoto = view.image_view_category
        var cardView = view.card_view_category

}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = MyViewHolder(parent.inflate(R.layout.category_list_row))

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {

    val category = categoryList[position]

    // Set height of cardview based on screen width
    val displayMetrics = context.resources.displayMetrics
    val finalHeight = displayMetrics.widthPixels / 2
    holder.cardView.layoutParams.height = finalHeight

    holder.categoryName.text = category.oc
    holder.categoryPhoto.loadUrl(category.icon)
}

override fun getItemCount(): Int {
    return categoryList.size
}}

Upvotes: 0

Views: 20389

Answers (3)

Rohit269
Rohit269

Reputation: 117

Do like this

class RecyclerListAdapter: RecyclerView.Adapter { var context: Context? = null var listData: ArrayList? = null

Step 1: Activity ref.................................. var activityref:MainActivity?=null

    constructor(context: Context?, listData: ArrayList<ItemDetails>?, activityref: MainActivity?) : super() {
        this.context = context
        this.listData = listData
        this.activityref = activityref
    }


    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewsHolder {
        val view = LayoutInflater.from(context).inflate(R.layout.row_list, parent, false)

        return ViewsHolder(view)
    }

    override fun getItemCount(): Int {
        return listData!!.size
    }

    override fun onBindViewHolder(holder: ViewsHolder?, position: Int) {
        holder?.item=listData?.get(position)
        holder!!.first!!.setText(holder.item?.First)
        holder.second!!.setText(holder.item?.Second)
        holder.third!!.setText(holder.item?.Third)

  Step 2  OnClick on item.....................       
        holder.third!!.setOnClickListener{
            activityref?.OnItemClicked(holder.item!!)
        }

    }


    class ViewsHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {


        var item:ItemDetails?=null

        var first: TextView? = null;
        var second: TextView? = null;
        var third: TextView? = null;

        init {
            first = itemView?.findViewById(R.id.first)
            second = itemView?.findViewById(R.id.second)
            third = itemView?.findViewById(R.id.third)

        }



    }


}

Upvotes: 2

Pedro Massango
Pedro Massango

Reputation: 5005

You can do it in your onBindViewHolder(...)

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    val category = categoryList[position]

    // Set height of cardview based on screen width
    val displayMetrics = context.resources.displayMetrics
    val finalHeight = displayMetrics.widthPixels / 2
    holder.cardView.layoutParams.height = finalHeight

    holder.categoryName.text = category.oc
    holder.categoryPhoto.loadUrl(category.icon)

    holder.categoryPhoto.setOnClickListener { view ->

       // categoryPhoto clicked.
       // start your activity here
    }      
}

Upvotes: 4

hluhovskyi
hluhovskyi

Reputation: 10106

Just add click listener as parameter to constructor of your adapter.

class CategoryAdapter(
        private val categoryList: List<Category>, 
        private val context: Context,
        private val onClickListener: (View, Category) -> Unit
) : RecyclerView.Adapter<CategoryAdapter.MyViewHolder>() {

    ...

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {

        val category = categoryList[position]

        // Set height of cardview based on screen width
        ...

        holder.itemView.setOnClickListener { view ->
            onClickListener.invoke(view, category)
        }      
    }

   ...
}

Then you can use as following:

fun initList() {
     adapter = CategoryAdapter(
         categoryList = ...,
         context = ...,
         onClickListener = { view, category -> openActivity(view, category) }
}

Off-top. Some optional improvements for code above

  1. Create typealias for lambda. Make your code more readable.

    typealias MyCategoryClickListener = (View, Category) -> Unit
    
    class CategoryAdapter(
        private val categoryList: List<Category>, 
        private val context: Context,
        private val onClickListener: MyCategoryClickListener
    ) : RecyclerView.Adapter<CategoryAdapter.MyViewHolder>() {
    
  2. Omit invoke call of listener. Lambda can be called just like function.

    holder.itemView.setOnClickListener { view ->
        onClickListener(view, category)
    }  
    
  3. Replace lambda with reference when creating adapter

     fun initList() {
         adapter = CategoryAdapter(
             categoryList = ...,
             context = ...,
             onClickListener = this::openActivity)
     }
    
     fun openActivity(view: View, category: Category) {
         ...
     }
    

Upvotes: 12

Related Questions