How to properly highlight selected item on RecyclerView?
This is much simple way to do it.
Have a private int selectedPos = RecyclerView.NO_POSITION;
in the RecyclerView Adapter class, and under onBindViewHolder method try:
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
viewHolder.itemView.setSelected(selectedPos == position);
}
And in your OnClick event modify:
@Override
public void onClick(View view) {
notifyItemChanged(selectedPos);
selectedPos = getLayoutPosition();
notifyItemChanged(selectedPos);
}
Works like a charm for Navigtional Drawer and other RecyclerView Item Adapters.
Note: Be sure to use a background color in your layout using a selector like colabug clarified:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/pressed_color" android:state_pressed="true"/>
<item android:drawable="@color/selected_color" android:state_selected="true"/>
<item android:drawable="@color/focused_color" android:state_focused="true"/>
</selector>
Otherwise setSelected(..) will do nothing, rendering this solution useless.
UPDATE [26/Jul/2017]:
As the Pawan mentioned in the comment about that IDE warning about not to using that fixed position, I have just modified my code as below. The click listener is moved to
ViewHolder
, and there I am getting the position usinggetAdapterPosition()
method
int selected_position = 0; // You have to set this globally in the Adapter class
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Item item = items.get(position);
// Here I am just highlighting the background
holder.itemView.setBackgroundColor(selected_position == position ? Color.GREEN : Color.TRANSPARENT);
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// Below line is just like a safety check, because sometimes holder could be null,
// in that case, getAdapterPosition() will return RecyclerView.NO_POSITION
if (getAdapterPosition() == RecyclerView.NO_POSITION) return;
// Updating old as well as new positions
notifyItemChanged(selected_position);
selected_position = getAdapterPosition();
notifyItemChanged(selected_position);
// Do your another stuff for your onClick
}
}
hope this'll help.