Styling AppCompat Button with Ripple Effect

Travis P
Black Lens
Published in
3 min readDec 27, 2016

No Drawables Required

This story is available in Thai

We all love AppCompat, right? We got Material Design UI backported to API7. What’s not to love?

Actually, there is. The only one thing I find it’s incredibly hard to accomplish. Yes, that’s right, styling the button!
I hate it when I have to create a StateListDrawable for every color I want and I have to separate the drawable-v21 ripple and the plain color one. Ugh.

After a lot of trial and error, stackoverflow, blog post and the official documentation, I finally found the simple solution for it.

This solution is based on AppCompat version 25.1.0, tested on API25, API16 emulators and a Google Pixel running Nougat 7.1.1.

  1. Change the background color using android:backgroundTint
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="@color/yellow"
android:text="Yellow Tint Button" />

By using the android:backgroundTint, your button gets the color and the ripple effect. Unfortunately, this works only on API21+.

On previous version of AppCompat (not sure which) , app:backgrountTint works fine on all API levels, you get a ripple on post-API21 and a StateListDrawable on pre-API21. Now if you try to use app:backgroundTint , the linter will complain and you don’t get a StateListDrawable on pre-API21. I don’t know if this is a bug or intentional but since the linter complains, I’m not comfortable using app:backgrountTint anymore.

2. Change the background color using android:theme

Another option is using theme. You can specified <item name=”colorButtonNormal”>@color/yellow</item> in your AppTheme and every button in your app gets the same color with a ripple effect on post-API21 and a StateListDrawable on pre-API21.

<!-- styles.xml -->
<style name="AppTheme.YellowButton">
<item name="colorButtonNormal">@color/yellow</item>
</style>
<!-- layout.xml -->
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.YellowButton"
android:text="Yellow Tint Button" />

Now we want to change a color of one particular button. What we can do is creating a new theme (preferably extended from AppTheme) and apply it to a single button. That’s it, this works on all API levels.

3. Ripple color

<!-- styles.xml -->
<style name="AppTheme.GreenRipple">
<item name="colorControlHighlight">@color/green</item>
</style>
<!-- layout.xml -->
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.GreenRipple"
android:text="Green Ripple Button" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?selectableItemBackground"
android:theme="@style/AppTheme.GreenRipple"
/>

This works the same way colorButtonNormal does but with colorControlHighlight the ripple color got changed.

You can also apply the theme and the android:background=”?selectableItemBackground” (or android:foreground) to any view and get the ripple effect.

On pre-API21 Button you get a StateListDrawable with a state pressed set to colorControlHighlight you specified.

Of course you can specify colorButtonNormal and colorControlHighlight together in a theme to get something like a green ripple on a yellow button.

4. Lowercase button text

In case your designers decided they don’t want an all caps text on a button.

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="textAllCaps=false"
android:textAllCaps="false" />

5. FloatingActionButton

<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
app:backgroundTint="@color/red"
app:rippleColor="@color/green"
app:srcCompat="@android:drawable/ic_dialog_email" />

Things behave differently for FAB, you can simply use app:backgroundTint and app:rippleColor (special thanks to Wanchuda Sukarrom)
They work perfectly on all API levels. But if somehow they don’t, this will.

<!-- styles.xml -->
<style name="AppTheme.RedFabGreenRipple">
<item name="colorAccent">@color/red</item>
<item name="colorControlHighlight">@color/green</item>
</style>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:theme="@style/AppTheme.RedFabGreenRipple"
app:srcCompat="@android:drawable/ic_dialog_email" />

That’s it for today, guys. If you have something to add, please do. If you find this useful, hit a 💚 recommend. Happy coding everyone.

--

--

Travis P
Black Lens

Android Developer, Kotlin & Flutter Enthusiast and Gamer