部分的Migration to MDC (Button編)

### はじめに
- Android Studio 4.1 でテンプレートアプリケーションに設定されているテンプレートが Material Design Component （以下MDC）になりました。[記事](https://android-developers.googleblog.com/2020/10/android-studio-41.html)
- ということでそろそろAndroidアプリの標準的ThemeはMDCに準拠していかないとならないなと思っていますが、そうもいかないよー:frowning2:と思っていたりもします。
- ただ、MDCに適応していくことで実装上の利点なんかもあるので、そういう意味では使いやすい部分から移行して行きたいところだったり。
- よくある AppCompat時代のButtonコンポーネントを、MDC対応Buttonコンポーネントにする方法をまとめておきます。

## よくあるAppCompatのButtonって？

### 想定
- iOSと同じようなデザインでと言われ、角丸、単色（通常色、選択色、無効色）のボタンを用意する感じです:anguished:
（もちろん`RippleEffect`は使っていないよ。）

#### 用意する

- アプリのテーマは`"Theme.AppCompat.DayNight.DarkActionBar"`あたりを設定と想定

##### ボタン色
 
``` colors.xml
    <color name="default_button_color">#ff0000ff</color>
    <color name="highlight_button_color">#ff007Fff</color>
    <color name="disable_button_color">#550000ff</color>
```

##### ボタンの選択状態と角丸設定（通常用）

``` shape_corner_radius_4dp_button_default_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="4dp" />
    <solid android:color="@color/default_button_color" />
</shape>
```

##### ボタンの選択状態と角丸設定（選択用）
``` shape_corner_radius_4dp_button_highlight_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="4dp" />
    <solid android:color="@color/disable_button_color" />
</shape>
```

##### ボタンの選択状態と角丸設定（選択用）
``` shape_corner_radius_4dp_button_disable_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="4dp" />
    <solid android:color="@color/highlight_button_color" />
</shape>
```

##### ボタンのselector設定
- 通常・選択・無効の状態を切り替えさせる為に`drawable`フォルダ内に用意

``` selector_default_button.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/shape_default_button" android:state_enabled="true" android:state_pressed="false" />
    <item android:drawable="@drawable/shape_default_button_highlighted" android:state_pressed="true" />
    <item android:drawable="@drawable/shape_default_button_disabled" android:state_enabled="false" />

</selector>
```


##### ボタンコンポーネント
``` xml
    <Button
        android:id="@+id/button_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/next"
        android:textColor="@color/white"
        android:background="@drawable/selector_default_button"
        ・・・
        />
```

### こんな感じ
![スクリーンショット 2020-10-27 22.07.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495289/0eb162ad-ae53-284b-91f8-4bd04ff14873.png)

### 何が嫌か
- ボタンの角丸サイズ違いや、色違いで`drawable`のリソースが増えていくのが非常に煩わしいところですね。

## ButtonだけをMDC対応した場合

- まずは MDCのライブラリは必要なのでgradleで取り込んでおきましょう。

``` build.gradle
dependencies {
    ・・・
    implementation 'com.google.android.material:material:1.2.1'
}
```

#### MDC用 Theme を用意
- MDC には AppCompatに存在していない必須となる設定値があるので、Button用にThemeを作成します。
- `colorOnPrimary` `colorPrimary` `colorOnSurface`は新しく必要ないろ定義です。
    - 文字色の指定ですので、任意の色を指定してあげてください。

``` theme.xml
    <!--  アプリ全体でMaterialComponentを適応できれば不要になるTheme  -->
    <style name="MDCButtonTheme" parent="Theme.MaterialComponents">
        <item name="colorOnPrimary">@color/base_text_color</item>
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorOnSurface">@color/base_text_color</item>
    </style>
```

#### MDC用 Style を用意
- `"@style/Widget.MaterialComponents.Button.UnelevatedButton"`は MDCで用意された、高さを表現させない場合のStyle定義
- `insetTop`と`insetBottom`は MDCのボタンに標準で設定されている Inset値（タッチ領域だけを広げる設定）を0に設定しています。 

``` style.xml
    <style name="MDCButtonStyle" parent="@style/Widget.MaterialComponents.Button.UnelevatedButton">
        <item name="android:insetTop">0dp</item>
        <item name="android:insetBottom">0dp</item>
    </style>
```

##### ボタンのselector設定
- 通常・選択・無効の状態を切り替えさせる為に`color`フォルダ内に用意
- 配置先が `drawable`から`color`にかわり、設定も色だけの設定にしています

``` selector_default_button.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/default_button_color" android:state_enabled="true" android:state_pressed="false" />
    <item android:color="@color/default_button_highlight_color" android:state_pressed="true" />
    <item android:color="@color/disable_button_color" android:state_enabled="false" />
</selector>
```
##### ボタンコンポーネント
- `Button`から`MaterialButton`に変更
- Theme と Style は必須となるので設定
- MDCのStyleにボタンの角丸`4dp`が設定されているので記述していませんが、MDCではXMLから`cornerSize`を利用する事で、角丸の値を設定できます。

``` xml
    <com.google.android.material.button.MaterialButton
        android:id="@+id/button_first"
        style="@style/MDCButtonStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:backgroundTint="@color/selector_default_button"
        android:text="@string/next"
        android:textColor="@color/white"
        android:theme="@style/MDCButtonTheme"
        ・・・
        />
```
### こんな感じ
![スクリーンショット 2020-10-27 22.35.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495289/abe9329f-8afc-3cc4-b084-4efc5e0cde75.png)

ほどんと同じボタンが出来上がりました。

- MDC のButtonを利用する事で、角丸や色の設定ごとにDrawableを増やす必要がなくなるので便利ですね。

## まとめ
- MDCへの切り替えは早めにしたいが、なかなか難しい場合、Buttonだけとかでも切り替えていってみよう。
- MDCのButtonを利用する事で、無駄にリソースを作る必要がなくなります！
- 本当はアプリのThemeを切り替えられるのがいいんでしょうけど:sweat: