androidkotlinonclicklistenercardviewandroid-imagebutton

Android - onClickListener not working for ImageButton in CardView


I have searched StackOverflow for similar questions and I have followed the instructions described there but I'm still not being able to make my onClickListener fire for my image button. Can someone help me?

I explain my problem in detail.

Here is my xml for the CardView:

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/item_title"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="16dp"
            android:textAppearance="?attr/textAppearanceHeadline6" />

        <TextView
            android:id="@+id/item_description"
            android:layout_below="@id/item_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?attr/textAppearanceBody1"
            android:paddingLeft="16dp"
            android:paddingRight="16dp" />

        <com.google.android.material.button.MaterialButton
            style="?attr/borderlessButtonStyle"
            android:id="@+id/workout_start_action"
            android:layout_below="@id/item_description"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/start_workout" />

        <ImageButton
            android:id="@+id/workout_delete_imgButton"
            android:layout_below="@id/item_description"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:src="@drawable/ic_delete"
            android:padding="8dp"
            android:contentDescription="FavButtonDesc" />
    </RelativeLayout>

</com.google.android.material.card.MaterialCardView>

Here is my adapter:

package com.example.workouttimer.adapter

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.example.workouttimer.R
import com.example.workouttimer.model.Workout


class WorkoutItemAdapter(private val context: Context,
                         private val dataset: List<Workout>
) : RecyclerView.Adapter<WorkoutItemAdapter.WorkoutItemViewHolder>() {

    class WorkoutItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
        val textView = view.findViewById<TextView>(R.id.item_title)
        val descriptionTextView = view.findViewById<TextView>(R.id.item_description)
        val imgDeleteButton = view.findViewById<ImageView>(R.id.workout_delete_imgButton)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WorkoutItemViewHolder {
        // create a new view
        val adapterLayout = LayoutInflater.from(parent.context)
                .inflate(R.layout.workout_list_item, parent, false)

        return WorkoutItemViewHolder(adapterLayout)
    }

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

    override fun onBindViewHolder(holder: WorkoutItemViewHolder, position: Int) {
        val item = dataset[position]
        holder.textView.text = item.workoutName
        holder.descriptionTextView.text = item.workoutDescription

        holder.imgDeleteButton.setOnClickListener(View.OnClickListener {
            /*fun onClick(v: View) {
                Toast.makeText(v.context, "BORRADO!!!", Toast.LENGTH_LONG)
            }*/

            fun onClick(position: Int) {
                Toast.makeText(this.context, "BORRADO!!!", Toast.LENGTH_LONG)
            }
        })
    }
}

What am I doing wrong? Thanks in advance.


Solution

  • Are you sure it's not fireing? I'm asking because you forgot to call show() on your toast. So in your on click try to log the event, or call show() on your toast like this:

    Toast.makeText(context, "BORRADO!!!", Toast.LENGTH_LONG).show()
    

    The real problem

    So the code below is an example of SAM conversion

    // What you did
    View.OnClickListener { // This is where the SAM conversion happens
        fun onClick(position: Int) { // This is a local function defined inside your lambda
            Toast.makeText(this.context, "BORRADO!!!", Toast.LENGTH_LONG)
            }
        }
    }
    
    // What you should've done
    View.OnClickListener { // This is where the SAM conversion happens
        Toast.makeText(this.context, "BORRADO!!!", Toast.LENGTH_LONG).show()
    }
    

    Because View.OnClickListener has only a single abstract method, by using SAM conversion, you don't have to specify which method you're overriding

    Edit: in Kotlin you can't override a method without the override keyword