material-componentsのProgressIndicatorを使ってみた

2020/12/17 に [material-components 1.3.0-beta1](https://github.com/material-components/material-components-android/releases/tag/1.3.0-beta01) が公開されました。
1.3.0 では `ProgressIndicator` と `TimePicker` が新たに追加されており、この記事では `ProgressIndicator` について紹介しようと思います。

## これまでの `ProgressBar` との違い

- Linear と Circular が別の View として扱うようになった
- MaterialTheming に準拠するようになった
- 色の指定がしやすくなった
- 角丸の指定ができるようになった
- 表示・非表示のアニメーションが使えるようになった



## 基本的な使い方

これまで style で Linear か Circular を出し分けていましたが、material-component 版では別の View として使います。

```xml
<com.google.android.material.progressindicator.LinearProgressIndicator
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
<com.google.android.material.progressindicator.CircularProgressIndicator
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/1425e151-1d32-e9d8-febf-8c50136c1c25.png" width="300px" />


常にアニメーションさせたい場合は `android:indeterminate="true"` を設定する。

```xml
<com.google.android.material.progressindicator.LinearProgressIndicator
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:indeterminate="true" />
<com.google.android.material.progressindicator.CircularProgressIndicator
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:indeterminate="true" />
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/17634f21-cb88-aa73-6bea-7f8191c785ec.gif" width="300px" />

`app:indicatorDirectionLinear` (Circular の場合は `app:indicatorDirectionCircular`) でインジケータの流れの向きも指定できる。

```xml
<com.google.android.material.progressindicator.LinearProgressIndicator
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:indeterminate="true"
    app:indicatorDirectionLinear="endToStart" />
<com.google.android.material.progressindicator.CircularProgressIndicator
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:indeterminate="true"
    app:indicatorDirectionCircular="counterclockwise" />
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/8dd7f685-2865-3ed0-767b-3a5ae8c0b74d.gif" width="300px" />


## 角丸

`app:trackCornerRadius` でインジケータの角丸の設定ができます。

```xml
<com.google.android.material.progressindicator.LinearProgressIndicator
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:trackCornerRadius="6dp" />
<com.google.android.material.progressindicator.CircularProgressIndicator
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:trackCornerRadius="6dp" />
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/c08a975c-bc42-6cbb-b979-4e9205d3a196.png" width="300px" />

## 色を変える

`app:indicatorColor` と `app:trackColor` で色を変えることができます。

```xml
<com.google.android.material.progressindicator.LinearProgressIndicator
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:trackColor="@color/blue"
    app:indicatorColor="@color/yellow" />
<com.google.android.material.progressindicator.CircularProgressIndicator
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:trackColor="@color/blue"
    app:indicatorColor="@color/yellow" />
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/f6af20cc-4794-19c9-34a6-db993f96e400.png" width="300px" />


色の配列を使うことで複数の色を合わせたインジケータにすることができる。
`app:indeterminateAnimationType="disjoint/contiguous"` でインジケータのアニメーションの種類も変えることができる。


```xml
<integer-array name="custom_progress_colors">
    <item>@color/yellow</item>
    <item>@color/blue</item>
    <item>@color/red</item>
</integer-array>

<com.google.android.material.progressindicator.LinearProgressIndicator
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:indeterminateAnimationType="disjoint"
    app:indicatorColor="@array/custom_progress_colors" />
<com.google.android.material.progressindicator.LinearProgressIndicator
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:indeterminateAnimationType="contiguous"
    app:indicatorColor="@array/custom_progress_colors" />
<com.google.android.material.progressindicator.CircularProgressIndicator
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:indicatorColor="@array/custom_progress_colors" />
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/692545d6-847b-fb53-94fc-1fd3a6910e19.gif" width="300px" />

## Standalone Indicator

インジケータの Drawable も提供されるようになり、Chip などに Indicator を埋め込むことができます。

```kotlin
val progressIndicatorSpec = CircularProgressIndicatorSpec(
    requireContext(),
    null,
    0,
    R.style.Widget_MaterialComponents_CircularProgressIndicator_ExtraSmall
)
val indeterminateDrawable = IndeterminateDrawable.createCircularDrawable(
    requireContext(),
    progressIndicatorSpec)
binding.chip.chipIcon = indeterminateDrawable
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/e9338ed1-43c8-768a-4347-3e187105309a.gif" width="300px" />

`CircularProgressIndicatorSpec` で Indicator のサイズや向きを設定できます。上記の例では `@style/Widget.MaterialComponents.CircularProgressIndicator.ExtraSmall` の style からサイズなどを取得して設定している。



この他にも表示・非表示のアニメーションの設定もできたり、インジケータの幅も変えることができます。
これまでの `ProgressBar` よりも表現できる幅が広がり、色の変更もしやすくなっているのでよきタイミングで置き換えていきたいですね。

## 参考
- https://developer.android.com/reference/android/widget/ProgressBar
- https://www.material.io/components/progress-indicators/android#using-progress-indicators