Styling AppCompat Button with Ripple Effect
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.
- 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.