38

I have buttons with different draw9patch png as background. Currently the buttons are controlled by selector which look something like this:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/pressed" android:state_pressed="true"/>
  <item android:drawable="@drawable/disabled" android:state_enabled="false"/>
  <item android:drawable="@drawable/focused" android:state_focused="true"/>
  <item android:drawable="@drawable/default"/>
</selector>

For the Android Lollipop they have a RippleDrawable for the touch effect, which goes something like this:

<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight">
    <item>
    ...
    </item>
</ripple>

Regarding the new touch ripple effect:

1: Can I set draw9patch as background for RippleDrawable?

2: How do I accomodate the above two different xml's I want to follow Material design? Do I have to fork out a new folder/layout xml for the new RippleDrawable?

Edric
  • 24,639
  • 13
  • 81
  • 91
Neoh
  • 15,906
  • 14
  • 66
  • 78

1 Answers1

78

1) Yes. See the documentation for RippleDrawable for more details on how layers are composited, but basically you want:

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

Or to also handle the disabled state in a clean way, you might want:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:attr/colorControlHighlight">
    <item>
        <selector>
            <item android:state_enabled="false">
                <nine-patch
                    android:src="@drawable/yourninepatch"
                    android:alpha="?android:attr/disabledAlpha" />
            </item>
            <item>
                <nine-patch android:src="@drawable/yourninepatch" />
            </item>
        </selector>
    </item>
</ripple>

2) Yes, you should place your ripple XML in drawable-v21.

alanv
  • 23,966
  • 4
  • 93
  • 80
  • I got the error `Element ripple must be declared` when I put xml inside **values-v21** folder. – Neoh Jul 08 '14 at 01:08
  • You also have and you're building against the L preview SDK? – alanv Jul 08 '14 at 02:14
  • It works fine if I put the xml in the usual res/drawable folder, but putting into values-v21 failed the build with error : `Error:Execution failed for task ':main:mergeDebugResources'. > Unsupported node 'item' in file /.../main/src/main/res/values-v21/button.xml` – Neoh Jul 08 '14 at 02:31
  • 1
    Sorry, I meant drawable-v21 directory. – alanv Jul 08 '14 at 08:13
  • 1
    there is any way to do this to all drawables automagically? so we don't have to create a copy and paste hell? – Rafael Sanches Oct 03 '14 at 02:11
  • You could write a script to do it, but you might want to reconsider why you have so many custom drawables that need foreground ripple feedback. Typically you would only use this for buttons. – alanv Oct 06 '14 at 23:58
  • I'm also getting "Element ripple must be declared" in values-v21. Hints? – roee88 Oct 22 '14 at 14:46
  • 1
    Read the answer and comments again. It goes in drawables-v21. – alanv Oct 22 '14 at 23:43
  • I don't get something. Suppose before Android Lollipop, I had a selector which has a color for each state (pressed, focused, checked, selected, and default), what should I do with Lollipop and above? Should I make a ripple drawable for each of them, setting the "color" attribute's value to the one I had before? – android developer Nov 17 '14 at 14:35
  • 2
    No, you only want one ripple element. Generally you would leave it at the default colorControlHighlight value, but you could also set the color to a color state list if you absolutely had to have different ripple colors on pressed and focused. Keep in mind you'll only ever see the ripple when an item is enabled and pressed or focused. – alanv Nov 17 '14 at 18:24
  • @alanv I see. What should be done in case I want to put the ripple effect inside CardView? Also, I'm not sure I understand your solution (on #1) : Do you set it as the background of the view, and the 9-patch somehow works as the boundary of the ripple effect? Shouldn't the hirerchy be the opposite since the 9-path restricts the ripple, and not vice versa ? – android developer Nov 27 '14 at 12:10