Android RecyclerView动作模式下条目高亮状态滚动后丢失问题求助
Hey there! I see the frustrating issue you're dealing with—those selected items losing their gray highlight when scrolling the RecyclerView is a super common pitfall tied to how RecyclerView reuses ViewHolders. Let's break down what's going wrong and fix it step by step.
The Root Cause
RecyclerView reuses ViewHolder instances to save memory and boost performance. When you scroll, a ViewHolder that was used for an off-screen item gets rebound to a new on-screen item. Right now, you're only setting the background color when the user long-clicks or clicks the item, but you're not updating the background based on the item's actual selected state when the ViewHolder is rebound. So when a reused ViewHolder comes back on screen, it keeps whatever background it had before, not the one matching the current item's selection status.
Step-by-Step Fix
Here's how to adjust your code to fix this:
Set the background in the
bindmethod first
At the very start of yourbindfunction, check if the current item is selected and set the background accordingly. This ensures every time a ViewHolder is bound (even when reused), it gets the correct state.Fix variable name typos
I noticed you haveselectListandselectedListin your code—those are different variables! That's probably causing hidden logic errors when checking if the selection list is empty. Stick to one consistent name (likeselectedListeverywhere).Use
getAdapterPosition()instead of a hardcodedposition
Thepositionvariable might not be accurate when ViewHolders are reused. UsegetAdapterPosition()to get the current, correct position of the ViewHolder.
Updated Code
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { // Ensure your data lists are properly declared here private List<Items> itemList; private List<Items> selectedList = new ArrayList<>(); private boolean isSelectMode = false; class MyViewHolder extends RecyclerView.ViewHolder { public void bind(Items currentItem) { // FIRST: Set background based on the item's selected state if (currentItem.getIsSelect()) { itemView.setBackgroundColor(Color.GRAY); } else { itemView.setBackgroundColor(Color.TRANSPARENT); } itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { isSelectMode = true; int currentPos = getAdapterPosition(); Items item = itemList.get(currentPos); if (item.getIsSelect()){ itemView.setBackgroundColor(Color.TRANSPARENT); item.setSelect(false); selectedList.remove(item); } else { itemView.setBackgroundColor(Color.GRAY); item.setSelect(true); selectedList.add(item); } // Fixed variable name to match selectedList if (selectedList.size() == 0){ isSelectMode = false; } return true; } }); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isSelectMode){ int currentPos = getAdapterPosition(); Items item = itemList.get(currentPos); if (item.getIsSelect()){ itemView.setBackgroundColor(Color.TRANSPARENT); item.setSelect(false); selectedList.remove(item); } else { itemView.setBackgroundColor(Color.GRAY); item.setSelect(true); selectedList.add(item); } // Fixed variable name here too if (selectedList.size() == 0){ isSelectMode = false; } } } }); } } // Don't forget to implement onCreateViewHolder and getItemCount as required }
Extra Tips
- If your
Itemsclass uses a boolean for selection, make sure it's properly updated and that you're not creating new instances ofItemswhen refreshing the list—otherwise, the selection state might get reset unexpectedly. - For cleaner separation of concerns, consider using a
SparseBooleanArrayto track selected positions instead of modifying theItemsobjects directly. This keeps your data model focused on its core purpose and avoids unintended side effects.
内容的提问来源于stack exchange,提问作者a awasi

