2

I have an activity with RecyclerView and each item in the list looks like below. The star should be clickable and when the user clicks it, it is expected to be changed to dark star. If the use clicks on the list item, it enters a new activity, where further details are provided corresponding to the list item selected. :

enter image description here

This is the XML of list item.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/cont_item_root"
android:layout_width="match_parent"
android:layout_height="85dp"
android:background="@drawable/background_state_drawable"
android:clickable="true"
>

<ImageView
    android:id="@+id/im_item_icon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingLeft="16dp"
    android:src="@mipmap/ic_tonality_black_36dp"
    android:layout_centerVertical="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<TextView
    android:id="@+id/lbl_item_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignTop="@+id/im_item_icon"
    android:layout_marginLeft="72dp"
    android:layout_marginRight="48dp"
    android:ellipsize="end"
    android:fontFamily="sans-serif"
    android:singleLine="true"
    android:text="Sois comme l'eau mon ami"
    android:textColor="@android:color/black"
    android:textSize="16sp" />

<TextView
    android:id="@+id/lbl_item_sub_title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/lbl_item_text"
    android:layout_marginLeft="72dp"
    android:layout_marginRight="48dp"
    android:ellipsize="end"
    android:fontFamily="sans-serif"
    android:singleLine="true"
    android:text="Mononc' J"
    android:textSize="14sp" />

<ImageView
    android:id="@+id/im_item_icon_secondary"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_alignParentRight="true"
    android:layout_centerVertical="true"
    android:padding="16dp"
    android:src="@mipmap/ic_star_border_black_24dp"
    android:background="@drawable/background_state_drawable"
    />

</RelativeLayout>

A nested class in Adapter handles the click events for me.

class DerpHolder extends RecyclerView.ViewHolder implements View.OnClickListener
    {
        private TextView title;
        private TextView subTitle;
        private ImageView thumbnail;
        private ImageView secondaryIcon;
        private View container;

        public DerpHolder(View itemView) {
            super(itemView);

            title = (TextView)itemView.findViewById(R.id.lbl_item_text);
            subTitle = (TextView)itemView.findViewById(R.id.lbl_item_sub_title);
            thumbnail = (ImageView)itemView.findViewById(R.id.im_item_icon);
            secondaryIcon = (ImageView)itemView.findViewById(R.id.im_item_icon_secondary);
            container = (View)itemView.findViewById(R.id.cont_item_root);
            container.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            Log.w("RecyclerView","Item with id : " + v.getId() + " touched");
            if(v.getId() == R.id.cont_item_root)
            {
                Log.w("RecyclerView","list item clicked");
                itemClickCallback.onItemClick(getAdapterPosition());
            }
            else
            {
                Log.w("RecyclerView","star clicked");
                itemClickCallback.onSecondaryIconClick(getAdapterPosition()); //not able to come here
            }
        }
    }

I am able to enter the first part of if, i.e. I am able to receive the click event of listItem click. However, when the user clicks star, it is also treated as if the whole list item is clicked as the star lies inside the container.

How can I receive the click on star seperately, so that the click on star is not treated as the click on list item?

EDIT

Adding the line android:descendantFocusability="blocksDescendants" in the RelativeLayout of list item fixed the issue. But can anyone please explain how it fixed it. By name, it is expected to block the descendants and eat the click events. However, the behaviour is opposite.

Naveen
  • 7,944
  • 12
  • 78
  • 165
  • Possible duplicate of [Button inside ListView not clickable](http://stackoverflow.com/questions/20709755/button-inside-listview-not-clickable) – OneCricketeer Apr 23 '17 at 20:00
  • 1
    Or better... http://stackoverflow.com/questions/30284067/handle-button-click-inside-a-row-in-recyclerview – OneCricketeer Apr 23 '17 at 20:02

4 Answers4

0

reverse the if / else statement and add a click listener for the star image. It should work since you want to trigger the listener for the recyclerview item if the star is not clicked

class DerpHolder extends RecyclerView.ViewHolder implements View.OnClickListener
    {
        private TextView title;
        private TextView subTitle;
        private ImageView thumbnail;
        private ImageView secondaryIcon;
        private View container;

        public DerpHolder(View itemView) {
            super(itemView);

            title = (TextView)itemView.findViewById(R.id.lbl_item_text);
            subTitle = (TextView)itemView.findViewById(R.id.lbl_item_sub_title);
            thumbnail = (ImageView)itemView.findViewById(R.id.im_item_icon);
            secondaryIcon = (ImageView)itemView.findViewById(R.id.im_item_icon_secondary);
            container = (View)itemView.findViewById(R.id.cont_item_root);
            container.setOnClickListener(this);
            secondaryIcon.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            Log.w("RecyclerView","Item with id : " + v.getId() + " touched");
            if(v.getId() == R.id.im_item_icon_secondary)
            {
                Log.w("RecyclerView","star clicked");
                itemClickCallback.onSecondaryIconClick(getAdapterPosition());
            }
            else
            {
                Log.w("RecyclerView","list item clicked");
                itemClickCallback.onItemClick(getAdapterPosition());
            }
        }
    }

Hope this helps

Omar El Halabi
  • 2,118
  • 1
  • 18
  • 26
0

Since you just want to get the click of the star, you should set the OnClickListener just for the star:

public DerpHolder(View itemView) {
        super(itemView);

        title = (TextView)itemView.findViewById(R.id.lbl_item_text);
        subTitle = (TextView)itemView.findViewById(R.id.lbl_item_sub_title);
        thumbnail = (ImageView)itemView.findViewById(R.id.im_item_icon);
        secondaryIcon = (ImageView)itemView.findViewById(R.id.im_item_icon_secondary);
        secondaryIcon.setOnClickListener(this);
    }
jonathanrz
  • 4,206
  • 6
  • 35
  • 58
0

You forgot to add onClick listener to secondaryIcon.

Try this:

class DerpHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
    private TextView title;
    private TextView subTitle;
    private ImageView thumbnail;
    private ImageView secondaryIcon;
    private View container;

    public DerpHolder(View itemView) {
        super(itemView);

        title = (TextView)itemView.findViewById(R.id.lbl_item_text);
        subTitle = (TextView)itemView.findViewById(R.id.lbl_item_sub_title);
        thumbnail = (ImageView)itemView.findViewById(R.id.im_item_icon);
        secondaryIcon = (ImageView)itemView.findViewById(R.id.im_item_icon_secondary);
        container = (View)itemView.findViewById(R.id.cont_item_root);

        container.setOnClickListener(this);
        secondaryIcon.setOnClickListener(this);    
    }

    @Override
    public void onClick(View v) {
        if(v.getId() == secondaryIcon.getId())
        {
            Log.w("RecyclerView","star clicked");
            itemClickCallback.onSecondaryIconClick(getAdapterPosition()); 
        }
        else
        {
            Log.w("RecyclerView","list item clicked");
            itemClickCallback.onItemClick(getAdapterPosition());
        }
    }
}

Hope this will help~

Ferdous Ahamed
  • 21,438
  • 5
  • 52
  • 61
0

You can also declare onclick item for specific views's of row like below in recycler adapter class.

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element

        holder.linRootMain.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Do your stuff here.
            }
        });

        holder.imgStart.setOnClickListner(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Do your stuff here.
            }
        });
}

I hope this will help you.