Search code examples
androidandroid-layoutandroid-5.0-lollipopmaterial-designandroid-appcompat

How can I modify ripple color when using ?attr/selectableItemBackground as background?


I've seen some SO questions and they gave some possible methods to achieve what I want. For example:

  1. Use colorControlHighlight attribute in styles.xml.

    Here is my styles-v21.xml:

    <style name="SelectableItemBackground">
        <item name="android:colorControlHighlight">#5677FC</item>
        <item name="android:background">?attr/selectableItemBackground</item>
    </style>
    

    And my widget:

    <TextView
        android:id="@+id/tv_take_photo_as_bt"
        android:layout_width="280dp"
        android:layout_height="48dp"
        android:text="@string/act_take_photo"
        style="@style/SelectableItemBackground"/>
    

    And it doesn't work. I also tried to add parent="Theme.AppCompat to "SelectableItemBackground" style, or change to colorControlHighlight(no android: prefix)", or change to ?android:attr/selectableItemBackground, neither is useful.

  2. Use backgroundTint attribute in layout.

    So I add android:backgroundTint="#5677FC" to my TextView. Still useless. Then I tried to change android:backgroundTintMode to src_in and src_atop, and they never make a difference.

So, how can I change ripple color when I use ?attr/selectableItemBackground as background. I only focus on Lollipop and above. Thank you in advance!


Solution

  • Finally I find the solution: instead of using android:colorControlHighlight directly in theme SelectableItemBackground, I should write another style:

    <style name="SelectableItemTheme">
        <item name="colorControlHighlight">@color/ripple_color</item>
    </style>
    

    Then:

    <style name="SelectableItemBackground">
        <item name="android:theme">@style/SelectableItemTheme</item>
        <item name="android:background">?attr/selectableItemBackground</item>
    </style>
    

    Finally add style="@style/SelectableItemBackground" to View in layout.xml.

    UPDATED ON 2016/8/26 After N's release, I found that sometimes we cannot use this method to set ripple color for some kind of View(for example, the CardView). Now I highly recommend developers using RippleDrawable, which can also be declared in xml. Here is an example:

    I want to show a ripple effect when user touches/clicks a CardView above API21, and of course there should be another kind of feedback before Lollipop. So I should write:

    <android.support.v7.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:foreground="@drawable/selectable_item_background"/>
    

    and selectable_item_background in drawable folder:

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_pressed="false" android:drawable="@android:color/transparent" />
        <item android:drawable="@color/color_clicked" />
    </selector>
    

    selectable_item_background in drawable-v21 folder:

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/ripple_black" />
    </selector>
    

    finally, the ripple_black in drawable(or drawable-v21) folder:

    <ripple
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:color="@color/color_clicked"
        tools:ignore="NewApi" /> <!--you can remove this line if it's in v21 folder-->
    

    That's it. For other views, maybe you should use android:background="@drawable/selectable_item_background". Don't forget to set an OnClickListener, OnTouchListener or something like those for them, otherwise ripple won't show.