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 should create a selector drawable with android:state_focused="true"
attribute as below
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@color/colorAccent"
android:state_focused="true" />
</selector>
</item>
</ripple>
then set this drawable as background of your RecyclerView row layout as
android:background="@drawable/selector"
I have tried several ways for hours and here is the two solutions I came out with. Both solutions assume I have my RecyclerView
declared as follows:
activity.xml
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_height="match_parent"
android:layout_width="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
Nothing special here, just a regular RecyclerView
declaration. Now let's see the other files, starting with the most easy and viable solution.
layout/item.xml
The two important attributes here in the item's root ViewGroup
are background
and clickable
.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/selector_item"
android:clickable="true"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal"
android:padding="16dp">
...
</LinearLayout>
drawable/selector_item.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/background_item_pressed"
android:state_pressed="true"
/>
<item
android:drawable="@drawable/background_item"
/>
</selector>
item.xml
No background
nor clickable
attribute here.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal"
android:padding="16dp">
...
</LinearLayout>
Adapter.java
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnTouchListener(itemTouchListener);
}
}
...
private View.OnTouchListener itemTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
v.setBackgroundResource(R.drawable.background_item_event_pressed);
break;
case MotionEvent.ACTION_CANCEL:
// CANCEL triggers when you press the view for too long
// It prevents UP to trigger which makes the 'pressed' background permanent which isn't what we want
case MotionEvent.ACTION_OUTSIDE:
// OUTSIDE triggers when the user's finger moves out of the view
case MotionEvent.ACTION_UP:
v.setBackgroundResource(R.drawable.background_item_event);
break;
default:
break;
}
return true;
}
};
...
}
I highly recommend using the first solution as it's easier to maintain and more powerful as it also allows you to add ripple effects (in the drawable/background_item...
XML files), which I believe isn't possible with solution 2.
If you manage to use an observable pattern flavor such as Otto or AndroidRx, you can follow how to highlight the background as explained above, and for each viewHolder's itemView you can subscribe to the observable and unsubscribe when it detaches from your recyclerview like I did here:
https://github.com/juanmendez/jm_android_dev/blob/master/01.fragments/06.fragments_with_rx/app/src/main/java/info/juanmendez/android/recyclerview/ui/listing/recyclerview/CountryHolder.java#L49
By the way for a quick demo my itemView is using linearLayout, so it was easy to set background color as yellow.
you can use this code out of Adapter
LinearLayoutManager RvLayoutManager = (LinearLayoutManager)rootlayout.getLayoutManager();
View itemSelected = RvLayoutManager.findViewByPosition(position);
itemSelected.setBackgroundColor(Color.Red);
You can add this to your row_item.xml
android:clickable="true"
android:background="?attr/selectableItemBackground"
For example:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:background="?attr/selectableItemBackground"
<!-- row content -->
If android version is Lolipop or greater, selector comes with ripple. And a highlight for other version. Hope it helps
there is no selector in RecyclerView like ListView and GridView but you try below thing it worked for me
create a selector drawable as below
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="@color/blue" />
</shape>
</item>
<item android:state_pressed="false">
<shape>
<solid android:color="@android:color/transparent" />
</shape>
</item>
</selector>
then set this drawable as background of your RecyclerView row layout as
android:background="@drawable/selector"