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

AndroidAndroid LayoutAndroid 5.0-LollipopMaterial DesignAndroid Appcompat

Android Problem Overview


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!

Android Solutions


Solution 1 - Android

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.

Solution 2 - Android

Ripple effect on pre- and Lollipop+ devices

harrane and Liuting are right. The accepted answer is not the best way. Let me show in code how to change ripple color for pre-Lollipop versions and higher

  1. Your AppTheme should inherit from any AppCompat theme and contain colorControlHighlight attribute (without 'android:' prefix)

     <!-- Application theme. -->
     <style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
     <item name="colorControlHighlight">#40ffffff</item>
     </style>
    
  2. Your view should contain clickable="true" (or should have a click listener set programmatically) and background should be "?attr/selectableItemBackgroundBorderless" or "?attr/selectableItemBackground" :

     <LinearLayout
     ...
     android:clickable="true"
     android:background="?attr/selectableItemBackgroundBorderless"/>
    

Note: that if your parent view has white background you won't see ripple effect since it's white. Change colorControlHighlight value for a different color

Also, if you want different ripple colors on different activities you can set personal theme for each activity in Manifest file, for example:

       <activity
        android:name="com.myapp.GalleryActivity"
        android:theme="@style/RedRippleTheme"
        />

Different ripple colors for different fragments in the same activity?##

You can change attributes of Activity Theme for each fragment in runtime. Just overwrite them before fragment was inflated with your custom style and apply to a current Theme:

in values/styles.xml

    <style name="colorControlHighlight_blue">
       <item name="colorControlHighlight">@color/main_blue_alpha26</item>
    </style>

Then, in your fragment before inflation in onCreateView():

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       getContext().getTheme().applyStyle(R.style.colorControlHighlight_blue, true); //blue ripple color
       View view = inflater.inflate(R.layout.my_fragment_layout, container, false);
       return view;
    }

This style will work only for this fragment


Different ripple color for different Views? (Lollipop +)##

You can change the ripple color for each view seperately using colorControlHighlight attribute, it doesn't work if you apply them to a view directly:

    <TextView
     ...
     colorControlHighlight="#40ffffff"/> <!-- DOESN'T WORK -->

you should apply it as a theme:

<TextView
  ...
  android:theme="@style/colorControlHighlight_blue"/>

P.S. Also, sometimes this approach helps if you have unknown issues with ripple and you can't figure it out. In my case, I used 3rd party sliding lib which messed up ripple effects for the entire layout and adding explicitly this theme to all clickable views worked out for me.

Solution 3 - Android

It's showing ripple effect with color on API +21, and simple gray background on press for API -21. Add this style:

<style name="AppTheme.MyRipple">
   <item name="colorControlHighlight">@color/your_color</item>
   <item name="android:background">?selectableItemBackgroundBorderless</item>
</style>

And set it to the view:

<Button
   ...
   android:theme="@style/AppTheme.MyRipple" />

Solution 4 - Android

The accepted answer is wrong.

The correct way to use is what Liuting mentioned in the comment. Use colorControlHighlight instead of android:colorControlHighlight for changing the default colorControlHighlight from AppCompat

*** Please refer to http://android-developers.blogspot.co.uk/2014/10/appcompat-v21-material-design-for-pre.html in the Theming section ***

Solution 5 - Android

Use the below steps:

1. Make changes to button view in your layout.xml
2. Add new styles in styles.xml

your_layout.xml

<Button
                        android:id="@+id/setup_submit_button"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="16dp"
                        android:text="@string/action_sign_in"
                        android:textStyle="bold"
                        android:background="@color/colorPrimary"
                        android:textColor="@color/white"
                        style="@style/SelectableItemBackground"
                        android:foreground="?android:attr/selectableItemBackground"/>

> -The style attribute calls the style that we created. > > -Foreground attribute calls the andorid's default selectable attribute.

styles.xml

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


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

Solution 6 - Android

This code works for me to create a ripple:

public static void setRippleDrawable(View view, int normalColor, int touchColor) {
    try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            RippleDrawable rippleDrawable = new RippleDrawable(ColorStateList.valueOf(touchColor), view.getBackground(), null);
            view.setBackground(rippleDrawable);
        } else {
            StateListDrawable stateListDrawable = new StateListDrawable();
            stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(touchColor));
            stateListDrawable.addState(new int[]{android.R.attr.state_focused}, new ColorDrawable(touchColor));
            stateListDrawable.addState(new int[]{}, new ColorDrawable(normalColor));
            view.setBackground(stateListDrawable);
            }
    } catch (Exception e) {
        Log.e(LOG_TAG, "" + e);
    }
}

I did not found any way to modify the selectableItemBackground attribute. That's why I did it like above.

Solution 7 - Android

In dark black theme(Or any other) app try to use like below first create ripple_effect.xml in drawable folder and add code like

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="#f5f5f5">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f5f5f5" />

        </shape>
    </item>

</ripple>

then set background to your Any view like Linear layout, Button, TextView etc.

 <TextView
                    android:id="@+id/tvApply"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@drawable/ripple_effect"
                    android:clickable="true"
                    android:text="APPLY"
                    android:textColor="#FFFFFF"
                    android:gravity="center"
                    android:textSize="@dimen/_8sdp"
                    android:padding="@dimen/_8sdp"
                    android:focusable="true" />

Solution 8 - Android

Use the foreground attribute as selectableItemBackground and background attribute as the color you want.

android:foreground="?attr/selectableItemBackground"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:background="@color/white"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionywwynmView Question on Stackoverflow
Solution 1 - AndroidywwynmView Answer on Stackoverflow
Solution 2 - AndroidKirill KarmazinView Answer on Stackoverflow
Solution 3 - AndroidMahdi KhansariView Answer on Stackoverflow
Solution 4 - AndroidharraneView Answer on Stackoverflow
Solution 5 - AndroidPrajwal WaingankarView Answer on Stackoverflow
Solution 6 - AndroidMikaView Answer on Stackoverflow
Solution 7 - AndroidOmkarView Answer on Stackoverflow
Solution 8 - AndroidTitto JoseView Answer on Stackoverflow