I have a Recycler View with the Images loaded from the Internal Storage. I want to Highlight the selected item when clicked. I tried a lot of thing but it was not working. A
You can use a StateListDrawable to achieve the desired effect.
Example
Create a new Drawable resource file in your drawable
directory with the following content:
selector_row.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Color when the row is selected -->
<item android:drawable="@android:color/darker_gray" android:state_pressed="false" android:state_selected="true" />
<!-- Standard background color -->
<item android:drawable="@android:color/white" android:state_selected="false" />
</selector>
Now simply use this StateListDrawable
as the background in the row-layout of your RecyclerView
row_recyclerview.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selector_row">
<!-- row content -->
</RelativeLayout>
Now as soon as the onClick()
method in your adapter is called you simply need to do the following:
// myBackground is the RelativeLayout root of your row
myBackground.setSelected(true);
The rows' background will have the color (in this case darker_gray) as long as you call myBackground.setSelected(false)
. Of course you should create a SparseBooleanArray for example in order to know which row is selected and which isn't since the rows will be reused when scrolling.
Edit: Remember selected items
The idea behind the SparseBooleanArray is to remember the items which are selected. Following a sample on how to use it:
public class MyImageAdapter extends RecyclerView.Adapter<MyImageAdapter.MyViewHolder> {
private SparseBooleanArray selectedItems;
// Other stuff [...]
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// Set the selected state of the row depending on the position
holder.myBackground.setSelected(selectedItems.get(position, false));
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
@Override
public void onClick(View v) {
// Save the selected positions to the SparseBooleanArray
if (selectedItems.get(getAdapterPosition(), false)) {
selectedItems.delete(getAdapterPosition());
myBackground.setSelected(false);
}
else {
selectedItems.put(getAdapterPosition(), true);
myBackground.setSelected(true);
}
}
}
}
This solution is more of an interactive look like the tableView in IOS. It'll highlight then unhighlight the cells.
@Override
public void onBindViewHolder(Cell holder, final int position) {
if(requests != null) {
holder.setView(requests.get(position), context);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
Logs.print("In OnClickListener", position + " selected");
}
});
holder.itemView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Logs.print("In Touch Handler", "A press has started");
v.setSelected(true);
break;
case MotionEvent.ACTION_UP:
Logs.print("In Touch Handler", "A press has been completed");
v.setSelected(false);
break;
case MotionEvent.ACTION_CANCEL:
Logs.print("In Touch Handler", "gesture aborted");
v.setSelected(false);
break;
}
return true;
}
});
}
}