(今から新規でアプリ作るなら、Material Components使うほうがオススメだよ!)
AppCompat.Buttonスタイル
とにもかくにも、スタイル定義を理解するためにも、AppCompat.Buttonを理解しましょう。
AppCompat.Buttonには主に以下の4種類のスタイルがあります。
- Widget.AppCompat.Button
- Widget.AppCompat.Button.Colored
- Widget.AppCompat.Button.Borderless
- Widget.AppCompat.Button.Borderless.Colored
| Default | backgroundTint="#4DB6AC" |
|---|---|
![]() |
![]() |
|
当然、Borderlessスタイルは背景がないのでtintされません。
AppCompat.Button
Androidの標準のボタンです。
旧マテリアルデザインではRaised Button、現在のマテリアルデザインではContained Buttonなどと呼ばれています
TextAppearance
?android:textAppearanceButton = TextAppearance.AppCompat.Widget.Button
AppCompat.Buttonの色
| enabled | disabled1 | |
|---|---|---|
| background | ?colorButtonNormal |
?colorButtonNormal |
| textColor2 | ?android:textColorPrimary |
?android:textColorPrimary |
| Ripple | ?colorControlHighlight |
- |
サイズ
AppCompat.ButtonのminHeightは48dpです。
しかし、実際表示してみると明らかにそれより小さいことがわかると思います。
これは、AppCompat.Buttonに指定されているbackgroundリソースにインセットが設けられているためです。
それぞれ、上下に6dp、左右に4dpのインセットが設定されています。
結果的に、
48dp (minHeight) - 6dp (insetTop) - 6dp (insetBottom) = 36dp
が見た目上の高さとなっています。
なお、この設定は旧マテリアルデザインのスペックに沿っています。
現在のマテリアルデザインガイドラインではコンポーネントのサイズと見た目のサイズを違えるという記述は消えているため、そのうちなくなるかもしれません。
(そもそもAppCompatよりもMaterial Componentsが推奨されていく可能性のほうが高いと思いますが)
elevation
AppCompat.Buttonの特徴としてelevationが設定されています。
ただし、このelevationはandroid:elevation="0dp"としても無効にすることはできません。
AppCompat.Buttonのelevationは、実際はandroid:stateListAnimatorによって制御されているため、無効にしたい場合はandroid:stateListAnimator="@null"とする必要があります。
AppCompat.Button.Colored
AppCompat.Buttonのサブスタイルで、ボタンに適用されるテーマのcolorAccentの色になるボタンです。
TextAppearance
TextAppearance.AppCompat.Widget.Button.Colored
AppCompat.Button.Coloredの色
| enabled | disabled | |
|---|---|---|
| background | ?colorAccent |
?colorButtonNormal |
| textColor | ?android:textColorPrimaryInverse |
?android:textColorPrimary1
|
| Ripple | ?colorControlHighlight |
- |
ただ単にtintする場合、AppCompat.ButtonとAppCompat.Button.Coloredどちらのスタイルを使うかについては、ボタンの明度がLightかDarkかで決めていいと思います。(ざっくりテキストがInverseかどうかの差です)
AppCompat.Button.Borderless
旧マテリアルデザインではFlat Button、現在はText Buttonと呼ばれているボタンです。
AppCompat.Buttonのbackgroundからshapeを除いているだけです。
TextAppearance
?android:textAppearanceButton = TextAppearance.AppCompat.Widget.Button
AppCompat.Button.Borderlessの色
| enabled | disabled1 | |
|---|---|---|
| background | - | - |
| textColor | ?android:textColorPrimary |
?android:textColorPrimary |
| Ripple | ?colorControlHighlight |
- |
AppCompat.Button.Borderless.Colored
AppCompat.Button.Borderlessのテキストに色付けをおこなったスタイルです。
AppCompat.Button.Borderlessの色
| enabled | disabled | |
|---|---|---|
| background | - | - |
| textColor | ?colorAccent |
?android:textColorSecondary1
|
| Ripple | ?colorControlHighlight |
- |
AppCompat.Button系スタイルの色はどう指定するのがよいか?
AppCompat.Button系スタイルの色の変え方には2種類あります。
1つは、最初に扱ったbackgroundTintを利用する方法です。
2つめは、ThemeOverlayを利用する方法です。
それぞれにメリット・デメリットが存します。
backgoundTint
backgroundTintとは、backgroundにあてた画像リソースにカラーフィルタをかけて色を変化させる属性です。
対応するminSdkVersionによって利用できるネームスペースが違うので気をつけてください。
| Androidバージョン | app:backgroundTint | android:backgroundTint |
|---|---|---|
| 21未満 | o | x |
| 21+ | o | o (推奨) |
backgroundTintに指定できるのは、ColorリソースまたはColorStateListリソースになります。
ColorStateListとは以下のような定義をしたリソースを指します。3
<selector>
<item android:state_enabled="false" android:color="@color/disabled_color"/>
<item android:color="@color/enabled_color"/>
</selector>
メリット
レイアウト時に即席でどんな色でも当てられるので、デメリットを気にしない場合はデザインの要求に対してコストが圧倒的に低いです。
<Button
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="@color/red"
android:text="Red Button"/>
デメリット
ステート対応がめんどくさい。
特殊なステートの場合はどっちにしろめんどくさいのですが、enabled - disabledの状態にすらColorStateListを作る必要があります。
将来的に、ColorStateListリソースがres/drawableに大量に作られて管理しきれなくなります。
ThemeOverlay
ThemeOverlayとは、View及びViewGroup階層でテーマの任意の変数をオーバーライドする手法です。
theme属性で指定しますが、これについても対応するminSdkVersionによって利用できるネームスペースが違います。
| Androidバージョン | app:theme4 | android:theme |
|---|---|---|
| 21未満 | o | x |
| 21+ | o | o (推奨) |
ThemeOverlayの適用範囲は、そのView及びそれ以下のView階層です。
ThemeOverlayを使ったボタンの色の変更は、以下のようにします。
<Button
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Red Button"
android:theme="@style/ThemeOverlay.Button.Red"/>
<style name="ThemeOverlay.Button.Red" parent="ThemeOverlay">
<item name="colorAccent">@color/red</item>
</style>
AppCompat.Button.Coloredの色は、先述したように?colorAccentが利用されるため、ThemeOverlayでその値だけ変更することでボタンの色が変更できます。
メリット
既存のボタンのステート定義を尊重しつつ、部分的に色を変更できる。
ThemeOverlayで当てる場合、?colorAccentのみを変更しているためdisabled状態は変わらず標準の表現が使われます。
逆にdisabledの色も任意にやりたい場合は、?colorButtonNormalを変更すればいいだけです。
デメリット
即席で色を当てる用途で使うには手間がかかる。
テーマを定義しないといけないため、1箇所でしか使わないボタンスタイルのためにやる作業としては、コストが重いように感じます。
ボタンのスタイル管理
ここまで、AppCompat.Button系スタイルの話しかしませんでしたが、独自スタイルにおいても同じことが言えます。
そのためAppCompat.Buttonを理解することで、独自定義の方法や何を懸念するべきかということも見えてくるはずです。
例えば今僕の携わっているプロジェクトでは、アウトラインボタンという枠線のみのボタンスタイルが定義されていますが、AppCompat.Buttonを参考にdrawable、textAppearance、styleの定義を行っています。
結局tintとthemeどちらを利用すればいいか
ハッキリ言って一貫した答えはありません。
画面仕様、デザインの指定から読み取ったり、デザイナーさんに訊いてみるのが手っ取り早いです。
目安としては
- disabledステートが必要なら
ThemeOverlay - とりあえず色付きのボタンが置ければいいなら
backgroundTint
くらいの認識でいいと思います。

