## How to create custom button styles using Android's AppCompat-v7:21
**Introduction**
AppCompat is an Android support library to provide backwards-compatible functionality for Material design patterns. It currently comes bundled with a set of styles in the `Theme.AppCompat` and `Widget.AppCompat` namespaces. However, there is a critical component missing which I would have thought essential to provide the a default from which we could inherit our styles: `Widget.AppCompat.Button`. Sure, there's `Widget.AppCompat.Light.ActionButton`, but that doesn't actually inherit from `Widget.ActionButton`, which does not inherit from `Widget.Button`, so we might get some unexpected behavior using that as our base button style, mainly because `Widget.ActionButton` strictly belongs in the `ActionBar`.
So, if we want to have a decently normal default button style related to AppCompat, we need to make it ourselves. Let's start by digging into the Android SDK to see how it's doing default styles.
**Digging In**
From `res/values/styles_material.xml` provided in the `android-sdk/platforms/android-21` directory of the Android SDK, we can find `Widget.Material.Button`:
```xml
```
We can keep most of the defaults, but remove `stateListAnimator` since that's not available below Lollipop. We also need to provide our own default values for `background` and `textAppearance` for our theming purposes, since neither of those values will work if we just steal them. Let's make a couple styles based on this:
**Our Styles**
```xml
```
As you can see, we created a couple new styles, one for a default rectangular button and one for a capsule-shaped button. We provide our own drawables for the background, and we inherit from the `TextAppearance.AppCompat.Button` for our textAppearance. Let's take a look at that theme just to see what it gives us by default.
In `styles_material`:
```xml
```
and `appcompat`:
```xml
```
Depending on your needs you may want to override these styles in your own theme, but they'll do for our purposes right now.
Note: If overriding `TextAppearance.AppCompat.Button`, my experience shows that `android:textColor` should be changed in the button theme, not in the `TextAppearance` style.
**Strategy**
So we want a unified theme for buttons - pressed, disabled, and enabled should be consistent for our default buttons. But we also want to take advantage of the new `ripple` effect in Lollipop. When I started retheming, I had a number of different drawable state lists and color state lists and shape state lists. It was getting messy. I figured there had to be a better way. So through lots of experimentation and research trying to grok how to efficiently build button themes, I came up with the following pattern:
1. Provide a `@drawable/button_default` in both `drawable` and `drawable-v21`.
2. Provide a single `@drawable/button_default_shape` in `drawable` that we can share for our button drawables in both versions.
3. Provide a single `@color/default_button_background` in `color` that we can share for our shape `solid`color.
4. Provide a single `@color/button_text_default` in `color` that we can share for the default button styles.
There's a problem with #2 and #3, though. Android's older XML parsers can't apply a `ColorStateList` as a `Solid`'s drawable or color attribute ([see Stack Overflow](http://stackoverflow.com/a/8169581/447934)). Since I wrote it already, I'm keeping that section to show how it *could* work.
To support older versions, we'll simply expand #2 a bit, and change #3:
2.1. Provide a single `@drawable/button_default_shape_selector` in `drawable` that we can share for our button drawables in both versions. This will define the drawable we will use for each state of the button.
2.2. Provide one `@drawable/button_default_shape_` for each supported button state. Each of these will use a different color for it's `solid` element. (Technically you could combine these into the shape selector file in 2.1, but this way you can preview what each state will look like in Android Studio.)
3.0. Create a `@color/default_button_background_` color instance for each state in `values/colors.xml`.
**Button Background Drawable**
Since we want to take advantage of the ripple effect on Lollipop, we'll need to provide two drawables of the same name in version-qualified drawable directories.
For the default version (below 21), we'll just make a shape that uses our custom color state list for its solid color:
```xml
```
Just a note, I tried just making it a `` with the color as its `- `, but it turns out the item *must* use `android:drawable`, which *must* come from the `drawables` directory. Thus, we make a basic rectangular shape.
For the lollipop version, we simply wrap the `` element inside of a `` element:
```xml
-
```
**Button Background Shape**
You'll notice that we're using the same shape for both drawables, so we can extract that into its own drawable `@drawable/button_default_shape`:
```xml
```
**Button Background Colors**
And of course, we need a `@color/button_default_background` state list:
```xml
```
I'll leave the `@color/button_text_default` as an exercize for the reader, but that's pretty much it! We now have a standard button style we can use throughout the app! To make that quick and easy, put it in your theme:
**Applying the Style**
```xml
```
**And Beyond**
To add a capsule button, you can follow the exact same steps as above, but change your `button_default_shape` to have a `` element defining whatever works for your theme. To match the previous theme, just use the `@color/button_default_background` that we created for our rectangular buttons. For different colored buttons, you'll still need to create a set of drawables, shapes, and color lists, but hopefully following this pattern, you'll be able to keep everything nicely organized, and follow a recognizable pattern throughout your codebase.