Keywords: RecyclerView | background color | single selection
Abstract: This article provides an in-depth exploration of implementing single selection background color changes in Android RecyclerView. By analyzing the core logic of the best answer, it explains how to use the selectedPosition variable to track selected items and efficiently update views with notifyItemChanged(). The article covers ViewHolder design, onBindViewHolder implementation, and performance optimization, offering complete code examples and step-by-step analysis to help developers master standardized methods for single selection highlighting in RecyclerView.
Core Mechanism of Single Selection Background Color Change in RecyclerView
In Android development, RecyclerView serves as a core component for list display, often requiring single selection functionality where visual feedback is crucial. Changing the background color of selected items provides intuitive user indication. The key to implementing this functionality lies in state management and view updates.
State Variable Design
First, two key variables need to be defined to track selection state:
int selectedPosition = -1;
int lastSelectedPosition = -1;
selectedPosition stores the position index of the currently selected item, with an initial value of -1 indicating no selection. lastSelectedPosition records the previously selected position, used to remove highlighting from old items when new items are selected. This design ensures only one item is highlighted at a time.
Optimized ViewHolder Design
The ViewHolder design directly impacts code maintainability and performance. Best practice involves using data binding or direct layout element references:
public class ViewHolder extends RecyclerView.ViewHolder {
ItemBinding binding;
public ViewHolder(ItemBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
Through ItemBinding (assuming ViewBinding or DataBinding), layout elements like LinearLayout or other container views can be safely accessed, avoiding performance overhead from repeated findViewById calls.
onBindViewHolder Implementation Logic
The onBindViewHolder method is central to implementing single selection functionality, handling both click events and view state updates:
public void onBindViewHolder(final ViewHolder holder, final int position) {
// Set click listener
holder.binding.getRoot().setOnClickListener(v -> {
lastSelectedPosition = selectedPosition;
selectedPosition = holder.getBindingAdapterPosition();
notifyItemChanged(lastSelectedPosition);
notifyItemChanged(selectedPosition);
});
// Set background color based on selection state
if (selectedPosition == holder.getBindingAdapterPosition()) {
holder.binding.linearLayout.setCardBackgroundColor(Color.LTGRAY);
} else {
holder.binding.linearLayout.setCardBackgroundColor(Color.WHITE);
}
}
Click event handling logic: When a user clicks an item, the current selectedPosition is first saved to lastSelectedPosition, then selectedPosition is updated to the clicked item's position. Subsequently, notifyItemChanged() is called to notify RecyclerView to update views at these two positions—ensuring the old selected item loses highlighting and the new selected item gains it.
Background color setting logic: By comparing the current item's position with selectedPosition, the method determines whether to apply highlight background color. Here, Color.LTGRAY represents the selected state, while Color.WHITE represents the default state.
Performance Optimization Considerations
Using notifyItemChanged() instead of notifyDataSetChanged() is key for performance optimization. notifyItemChanged() updates only the specified position's view, whereas notifyDataSetChanged() triggers a complete list redraw, which can cause performance issues with large datasets.
Additionally, ensure view lookups are completed in the ViewHolder constructor to avoid repeated findViewById calls in onBindViewHolder, aligning with RecyclerView's view recycling mechanism.
Complete Implementation Example
Integrating with the original question's code structure, a complete adapter implementation is as follows:
public class RecyclerDataAdapter extends RecyclerView.Adapter<RecyclerDataAdapter.ViewHolder> {
private String[] android_versionnames;
private int selectedPosition = -1;
private int lastSelectedPosition = -1;
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.itemView.setOnClickListener(v -> {
lastSelectedPosition = selectedPosition;
selectedPosition = holder.getBindingAdapterPosition();
if (lastSelectedPosition != -1) {
notifyItemChanged(lastSelectedPosition);
}
notifyItemChanged(selectedPosition);
});
// Set text content
holder.tv1.setText(android_versionnames[position]);
// Set background color
if (selectedPosition == position) {
holder.row_linearlayout.setBackgroundColor(Color.LTGRAY);
} else {
holder.row_linearlayout.setBackgroundColor(Color.WHITE);
}
}
// ViewHolder and other methods remain unchanged
}
This implementation preserves the original code structure while integrating single selection highlighting. Note the addition of a lastSelectedPosition != -1 check to avoid updating invalid positions in the initial state.
Extensions and Variations
In practical development, more complex selection logic may be required, such as:
- Multi-selection mode: Use
Set<Integer>instead ofselectedPositionto store multiple selected positions. - Persistent selection state: Restore selection state after configuration changes (e.g., screen rotation) by saving
selectedPositioninonSaveInstanceState. - Custom highlight effects: Beyond background color, modify text color, add borders, or use animation transitions.
By understanding the core state management and view update mechanisms, developers can flexibly adapt to various selection requirements.