How can I modify ripple color when using ?attr/selectableItemBackground as background?
AndroidAndroid LayoutAndroid 5.0-LollipopMaterial DesignAndroid AppcompatAndroid Problem Overview
I've seen some SO questions and they gave some possible methods to achieve what I want. For example:
-
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 tocolorControlHighlight(no android: prefix)"
, or change to?android:attr/selectableItemBackground
, neither is useful. -
Use
backgroundTint
attribute in layout.So I add
android:backgroundTint="#5677FC"
to myTextView
. Still useless. Then I tried to changeandroid:backgroundTintMode
tosrc_in
andsrc_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
-
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>
-
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"