66

How to specify android:state_selected inside a RippleDrawable

I have following xml for ripple drawable but background color doesn't show up when I set myView.setSelected(true);

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

    <item android:id="@android:id/mask">
        <shape>
            <solid
                android:color="@color/black" />
        </shape>
    </item>


    <item android:state_selected="true">
        <shape>
            <solid
                android:color="#EEEEEE" />
        </shape>
    </item>


    <item>
        <color android:color="#FFFFFF" />
    </item>

</ripple>
Sohaib
  • 10,941
  • 9
  • 32
  • 34

4 Answers4

117

Found the answer, just in case someone else having the same problem

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


    <item>
        <selector>
            <item android:state_selected="true">
                <color android:color="#EEEEEE" />
            </item>

            <item android:state_activated="true">
                <color android:color="#EEEEEE" />
            </item>

            <item>
                <color android:color="#FFFFFF" />
            </item>
        </selector>
    </item>


</ripple>
Sloy
  • 2,975
  • 3
  • 20
  • 21
Sohaib
  • 10,941
  • 9
  • 32
  • 34
  • 1
    You don't need to set a mask layer here since your mask and content have identical bounds and opacity. Removing the mask will improve performance considerably. – alanv Dec 16 '14 at 19:12
  • 1
    Thanks @alanv. Removed the mask. You mentioned identical bounds and opacity, how does opacity work in a mask? – Sohaib Dec 18 '14 at 03:16
  • 7
    For some reason if you use a transparent color for selector normal state then you should use a mask otherwise the ripple will not be drawn. – vovahost May 24 '15 at 20:23
  • @vovahost hi, you are right about the transparent color problem, but even with a mask, the ripple appears but the color isn't 100% opaque, it has some transparency. do you have any idea how to handle this? – andrei Jun 12 '15 at 10:44
17

To add to @Sohaib 's answer:

@Alanv is right that the OP didn't need a mask. But if one of your selector states is transparent and you need a mask it goes here:

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

    <!-- mask here... -->
    <item android:id="@android:id/mask">
        <color android:color="@color/black"/> <!-- any color will do -->
    </item>

    <item>
        <selector>
            <!-- ... NOT here. -->
            <item android:state_selected="true">
                <color android:color="@color/blue"/>
            </item>

            <item android:state_activated="true">
                <color android:color="@color/red"/>
            </item>

            <item>
                <color android:color="@color/transparent"/>
            </item>
        </selector>
    </item>
</ripple>

I initially had the mask inside my selector and :boom:

tir38
  • 9,810
  • 10
  • 64
  • 107
10

Combining the above answer with other answers from:

What should be the color of the Ripple, colorPrimary or colorAccent? (Material Design)

Gives a nice ripple effect which also works for when the item is in a selected state.

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?attr/colorControlHighlight">
<!-- Ripple mask - applied to all selector states -->
<item android:id="@android:id/mask">
    <color android:color="#42ffffff" />
</item>
<!-- Selected state of item -->
<item>
    <selector>
        <item android:state_selected="true">
            <color android:color="?attr/colorAccent" />
        </item>
    </selector>
</item>
</ripple>

This goes in your drawable-v21 folder, for other platforms you can just create a selector which uses the accent color:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/accent" android:state_selected="true"/>
    <item android:drawable="@color/accent" android:state_pressed="true"/>
</selector>
Community
  • 1
  • 1
Meanman
  • 1,474
  • 20
  • 17
3

I wanted to mimic the behavior of the Material Design checkboxes but I couldn't get them right until I used a ColorStateList like this:

In drawable-v21/bg_checkbox_ripple.xml

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

In color/checked_accent_statelist.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="?colorControlHighlight" android:state_checked="false"/>
    <item android:color="?android:textColorHighlight" android:state_checked="true"/>
</selector>

The attribute "?android:textColorHighlight" is your accent color but with the right transparency for using it in ripples (I think it is 26%).

Also, you should provide a fallback for pre API 21 devices in drawable/bg_checkbox_ripple.xml

<?xml version="1.0" encoding="utf-8"?>
<selector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:exitFadeDuration="@android:integer/config_shortAnimTime">
    <item>
        <shape android:innerRadius="24dp" android:shape="oval">
            <solid android:color="@color/checked_accent_statelist"/>
        </shape>
    </item>
</selector>