'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 |