Reputation: 11695
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 to colorControlHighlight(no android: prefix)"
, or change to ?android:attr/selectableItemBackground
, neither is useful.
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!
Upvotes: 132
Views: 84513
Reputation: 116332
If you want to do it programmatically, this solution I've worked on should work at least for most of the cases:
fun View.setBackgroundTintColor(@ColorInt color: Int) {
val background = background
if (background is RippleDrawable) {
val newBackground = background.mutate() as RippleDrawable
if (color != 0)
newBackground.setColor(ColorStateList.valueOf(color))
this.background = newBackground
} else {
if (color == 0)
ViewCompat.setBackgroundTintList(this, null)
else
ViewCompat.setBackgroundTintList(this, ColorStateList.valueOf(color))
}
}
Usage:
yourView.setBackgroundTintColor(0xffff0000.toInt())
And to reset to normal:
yourView.setBackgroundTintColor(0)
As you can see, you should know that using it might make the View have a new background, sadly.
Upvotes: 0
Reputation: 1234
In your xml set background:
<View
android:id="@+id/click_view"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:background="?attr/selectableItemBackgroundBorderless" <!-- Set ripple this way -->
android:contentDescription="@null" />
And in your code change color of it:
// Take borderless ripple
val ripple = clickView.background as? RippleDrawable
// Change color here
ripple?.setColor(ColorStateList.valueOf(Color.RED))
Don't know how it works with Lollipop.
Upvotes: 0
Reputation: 2710
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>
Upvotes: 13
Reputation: 3100
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" />
Upvotes: 0
Reputation: 141
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.
Upvotes: 0
Reputation: 435
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" />
Upvotes: 16
Reputation: 6736
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"
/>
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
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.
Upvotes: 68
Reputation: 72
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"
Upvotes: -1
Reputation: 969
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 *
Upvotes: 8
Reputation: 11695
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.
Upvotes: 183