Home » Android » Android Ripple Effect Overridden by Selected State

Android Ripple Effect Overridden by Selected State

Posted by: admin June 15, 2020 Leave a comment

Questions:

After having been looking for a while I’ve not been able to find an answer to this…

I have a recycler view with items which when selected have a red background and white text (beforehand the background is white and text is black). To do this I am using a selector.

I have recently tried to add a ripple effect to this, but unless I long click on the item the background of the item goes straight to red without the ripple. I am assuming this is because the selector state state_selected overrides the ripple on sate_pressed?

Does anyone know if there is a way around this? Here is the selector code I use:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@android:color/holo_red_dark" >

    <item>
        <selector xmlns:android="http://schemas.android.com/apk/res/android" >
            <item
                android:drawable="@drawable/ripple"
                android:state_pressed="true"/>
            <item
                android:drawable="@android:color/holo_red_dark"
                android:state_selected="true"/>
            <item android:drawable="@android:color/white"/>
        </selector>
    </item>

</ripple>

Thanks in advance!

How to&Answers:

To create a selector background that has a ripple effect and shows selected status I do the following:

Start by defining your highlight color, with some transparency:

  • values/colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="selector_color">#660000ff</color>
</resources>

You probably want to have compatibility pre-lollipop. Put a typical old-school selector inside drawable folder:

  • drawable/selector_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/selector_color" android:state_pressed="true"/>
    <item android:drawable="@color/selector_color" android:state_selected="true"/>
    <item android:drawable="@android:color/transparent"/>
</selector>

And then add the following layer drawable inside drawable-v21 folder:

  • drawable-v21/selector_background.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <selector>
            <item android:state_selected="true"
                android:drawable="@color/selector_color" />
            <item android:drawable="@android:color/transparent" />
        </selector>
    </item>
    <item>
        <ripple android:color="@color/selector_color">
            <item android:id="@android:id/mask">
                <color android:color="@android:color/white" />
            </item>
        </ripple>
    </item>
</layer-list>

Now you can use @drawable/selector_background for your selector.

Answer:

It will be better if you wrap your recyclerview item view in FrameLayout and set android:background=”?selectableItemBackground” of FrameLayout and the child layout of FrameLayout background=”@drawable/background”

background.xml

<item android:drawable="@color/red" android:state_selected="true"/>
<item android:drawable="@color/red" android:state_focused="true"/>
<item android:drawable="@color/red" android:state_pressed="true"/>
<item android:drawable="@color/white"/>

And then child layout must has attribute android:duplicateParentState=”true”

Answer:

So I have another case in which I had to use selector as well as layer list for that

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true">
        <ripple xmlns:android="http://schemas.android.com/apk/res/android"
                android:color="@color/colorRipple">
            <item>
                <layer-list>
                    <item>
                        <shape android:shape="rectangle">
                            <solid android:color="@color/grey_very_light" />
                        </shape>
                    </item>
                    <!-- ripple color -->
                    <item android:bottom="1dp">
                        <shape android:shape="rectangle">
                            <solid android:color="@color/c_unread_notifications_item" />
                        </shape>
                    </item>

                </layer-list>
            </item>
        </ripple>

    </item>
    <item>
        <ripple xmlns:android="http://schemas.android.com/apk/res/android"
                android:color="@color/colorRipple">
            <item>
                <!-- ripple color -->
                <layer-list>

                    <item>
                        <shape android:shape="rectangle">
                            <solid android:color="@color/grey_very_light" />
                        </shape>
                    </item>

                    <item android:bottom="1dp">
                        <shape android:shape="rectangle">
                            <solid android:color="@color/white" />
                        </shape>
                    </item>

                </layer-list>
            </item>
        </ripple>
    </item>
</selector>

This worked, for your need what you can do it just replace the item under ripple with your item shape if you don’t have any layering.
Hope this helps