Android Ripple Effect Overridden by Selected State
Asked Answered
A

3

8

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!

Afrikah answered 12/5, 2015 at 10:40 Comment(0)
G
17

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.

Glanville answered 10/7, 2015 at 8:2 Comment(4)
For others, when using with buttons, this layer-list approach works, but you need to use state_activatedDee
Although the ripple works flawlessly, the list item does not remain selected.Waterlogged
This works very well. The ripple effect colour and the selected colour should be different so that the user can see the ripple effect when selecting the already selected item.Krispin
Very nice solution, but as @Dee already mentioned you need to use: "state_activated" instead of "state_selected". Thanks!Spondaic
C
1

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

Crosslegged answered 16/6, 2017 at 7:21 Comment(0)
E
0

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"

Evaluate answered 16/7, 2015 at 10:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.