'RecyclerView's onClick won't work clicking items, only when you click BETWEEN items

I'm learning Android and I'm testing things with RecyclerView. I wanted to add an OnItemClickListener, I wanted to see if works so I made a Toast appear each time I click on items, but something weird happens, only triggers when I click BETWEEN cards of Recycler, not when I click items. I've been looking for people with the same problem but didn't found anything.

This is the RecyclerAdapter and the Activity for it.

Adapter

public class CardAdapter extends ListAdapter<Card, CardAdapter.CardHolder> {

    private OnItemClickListener listener;
    private Context mContext;
    private Intent myIntent;

    protected CardAdapter() {

        super(DIFF_CALLBACK);
    }

    private static final DiffUtil.ItemCallback<Card> DIFF_CALLBACK = new DiffUtil.ItemCallback<Card>() {
        @Override
        public boolean areItemsTheSame(Card oldItem, Card newItem) {
            return oldItem.getId() == newItem.getId();
        }

        @Override
        public boolean areContentsTheSame(Card oldItem, Card newItem) {
            return oldItem.getCardImage() == newItem.getCardImage() &&
                    oldItem.getCardName().equals(newItem.getCardName()) &&
                    oldItem.getCardCode().equals(newItem.getCardCode()) &&
                    oldItem.getCardSet().equals(newItem.getCardSet()) &&
                    oldItem.getQuantity() == newItem.getQuantity() &&
                    oldItem.getRarity().equals(newItem.getRarity());

        }
    };

    @NonNull
    @Override
    public CardHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.card_item, parent, false);
        mContext = parent.getContext();
        return new CardHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull CardHolder holder, int position) {
        Card currentCard = getItem(position);
        Picasso.with(mContext).load(currentCard.getCardImage()).fit().centerInside().into(holder.cardImage);
        holder.cardName.setText(currentCard.getCardName());
        holder.cardCode.setText(currentCard.getCardCode());
        holder.cardSet.setText(currentCard.getCardSet());
        holder.rarity.setText(currentCard.getRarity());


    }


    class CardHolder extends RecyclerView.ViewHolder {

        private ImageView cardImage;
        private TextView cardName;
        private TextView cardCode;
        private TextView cardSet;
        private TextView quantity;
        private TextView rarity;

        public CardHolder(View itemView) {
            super(itemView);
            cardImage = itemView.findViewById(R.id.cardImage);
            cardName = itemView.findViewById(R.id.cardName);
            cardCode = itemView.findViewById(R.id.cardCode);
            cardSet = itemView.findViewById(R.id.cardSet);
            rarity = itemView.findViewById(R.id.cardRarity);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    Toast.makeText(mContext, "epaepa", Toast.LENGTH_SHORT).show();
                    Log.d("LogDiaViewHolder","epaepa");

                }
            });
        }

        public ImageView getCardImage() {
            return cardImage;
        }

    }

    public interface OnItemClickListener {
        void onItemClick(Card card);
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }
}

Activity

public class CardListActivity extends AppCompatActivity {

    private CardViewModel cardViewModel;
    private View decorView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_card_list);

        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);

        final CardAdapter adapter = new CardAdapter();
        recyclerView.setAdapter(adapter);

        cardViewModel = ViewModelProviders.of(this).get(CardViewModel.class);
        cardViewModel.getAllCards().observe(this, new Observer<List<Card>>() {
            @Override
            public void onChanged(List<Card> cards) {
                adapter.submitList(cards);
            }
        });

        decorView = getWindow().getDecorView();
        decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
            @Override
            public void onSystemUiVisibilityChange(int visibility) {
                if (visibility == 0) {
                    decorView.setSystemUiVisibility(hideSystemBars());
                }
            }
        });

    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            decorView.setSystemUiVisibility(hideSystemBars());
        }
    }

}

If someone wants the full project I'll leave repo here: https://github.com/nochuckles/BattleSpiritsCBDB

Any help would be nice, thanks!



Solution 1:[1]

I fixed it! Apparently if you have the attribute:

clickable:true

on your CardView this will happen.

I don't know why, I was testing different things and when I removed that, it started to work perfectly. I don't know why this happens, I'll do some research but if someone has some information on this, I'd really appreciate it, thanks!

Solution 2:[2]

Set your OnClickListeners in BindViewHolder

@Override
    public void onBindViewHolder(@NonNull CardHolder holder, int position) {
        Card currentCard = getItem(position);
        Picasso.with(mContext).load(currentCard.getCardImage()).fit().centerInside().into(holder.cardImage);
        holder.cardName.setText(currentCard.getCardName());
        holder.cardCode.setText(currentCard.getCardCode());
        holder.cardSet.setText(currentCard.getCardSet());
        holder.rarity.setText(currentCard.getRarity());

        //example
        holder.cardName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Toast.makeText(mContext, "epaepa", Toast.LENGTH_SHORT).show();
                Log.d("LogDiaViewHolder","epaepa");

            }
        });
}

Solution 3:[3]

It's not at you adapter to display the Toast, you must use you interface OnItemClickListener to notify your activity when item tapped. For that your activity must implements this interface and the onItemClick method:

public class CardListActivity extends AppCompatActivity implements OnItemClickListener {
    ....
    void onItemClick(Card card) {
         Toast.makeText(mContext, "epaepa", Toast.LENGTH_SHORT).show();
                Log.d("LogDiaViewHolder","epaepa");
    }
}

To launch the onItemClick event in adapter you must pass to the adapter an instance of your interface

public class CardAdapter extends ListAdapter<Card, CardAdapter.CardHolder> {
    //....
    private OnItemClickListener mListener

    protected CardAdapter(OnItemClickListener listener) {
        super(DIFF_CALLBACK);
        this.mListener = listener;
    }
}

and then call the interface method when item click

itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                 mListener.onItemClick(v)
            }
        });

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 a_local_nobody
Solution 2 Vince VD
Solution 3 SebastienRieu