RatingBarの画像をカスタマイズする方法

# はじめに
RatingBarは評価に使われるツールです
ユーザーに商品の評価などをしてもらうときに便利な機能ですね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252283/5954a014-4d35-85de-645b-0f7c4689d832.png)

https://developer.android.com/reference/android/widget/RatingBar

色のカスタマイズなどは容易なのですが、たまに星の画像（形）を変更してほしいという依頼がありします
というわけでカスタマイズ方法の紹介です
ただし、修正方法は公式推奨の変更方法がないので、あまり推奨はできません
RatingBarは元々OSバージョンやユーザー設定によってバグが起きやすいの機能なので変更したくないというのが本音・・
今回はなるべくバグが起きない、且つ、簡単な方法を紹介します（大手サービスでしばらく運用していますが今のところ問題は起きていません）

# 調べたやり方
参考サイト：
RatingBarの画像を変更してみる
https://korsakov.hatenadiary.org/entry/20120317/1331975422
RatingBar の星の色を黄金に変更する
https://note.com/countablepad/n/n8df4e66f08c0

ネットを調べてみるとあまり情報がありませんでした・・
数少ないものを参考にさせていただくとStyleを作成して、そこにレイアウトファイルを作成して設定、レイアウトファイルに画像を設定するというやり方が見つかりました

fragment.xml
``` xml
<RatingBar 
    style="@style/MyRating"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
```

style.xml
``` xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="MyRating" parent="@android:style/Widget.RatingBar">
        <item name="android:progressDrawable">@drawable/rating</item>
        <item name="android:indeterminateDrawable">@drawable/rating</item>
        <item name="android:minHeight">38dip</item>
        <item name="android:maxHeight">38dip</item>
        <item name="android:thumb">@null</item>
        <item name="android:isIndicator">true</item>
    </style>
</resources>
```
rating.xml
``` xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+android:id/background" 
        android:drawable="@drawable/star01" />
    <item android:id="@+android:id/secondaryProgress" 
        android:drawable="@drawable/star02" />
    <item android:id="@+android:id/progress" 
        android:drawable="@drawable/star03" />
</layer-list>
```

あとは画像ファイルを星が空の時、星が半分の時、星がフルの時と３パターン用意します（star01,02,03）
もちろんこの方法でも変更可能です

# 考えたやり方
上記の設定をみると独自Styleの親はstyle/Widget.RatingBarですが、それでいいの？という疑問が出てきました
実際には環境に合わせてStyleが変わるようなので、依頼内容が既存と同じ動き、サイズでとなるとちょっと心配です
コードを見てみるとSDK内のStyleが実際には使われているようです
そこでprogressDrawableの設定だけ直接fragment.xmlに設定すれば既存のStyleが使用されるからより安全なのでは？という考えにたどり着きました
また設定も上記の方法より楽です！
（調べたところindeterminateDrawableなどの設定は不要のようです）

fragment.xml
``` xml
    <RatingBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:progressDrawable="@drawable/MyRatingStar" />
```

MyRatingStar.xml
``` xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@android:id/background"
        android:drawable="@drawable/rating_empty" />
    <item
        android:id="@android:id/secondaryProgress"
        android:drawable="@drawable/rating_half" />
    <item
        android:id="@android:id/progress"
        android:drawable="@drawable/rating_full" />
</layer-list>
```

あとは画像を３つ用意するだけですが、ここで問題になるのが画像サイズです
画像サイズを間違えると一部かけてしまったり、余白が既存と変わってしまいます
余白は好みによって変えて良いと思いますがなるべく既存に合わせた方が安全だと思います

調べてみると
/Users/{user_name]/Library/Android/sdk/platforms/android-32/data/res/value/styles_material.xml
が採用されていて、
/Users/{user_name]/Library/Android/sdk/platforms/android-32/data/res
をみるとstar画像が複数サイズありました
検証してみるとic_star_black_48dp.png,ic_star_half_black_48dp.png
が実際に使われているのと同サイズのようです（empty画像はalphaとtintを変えて使用しています）
これらはマテリアルデザインが採用されているか？どのSDKを使用しているか？などによって変わってくると思うので、お使いの環境から適切な画像を調べる必要がありそうです
（fragment.xmlのRatingBarの使用クラスを調べる）

今回の画像サイズはこちら
|フォルダ  |pixel * pixel |
|---|---|
|mdpi  |48 * 48  |
|hdpi  |72 * 72  |
|xhdpi  |96 * 96  |
|xxhdpi  |144 * 144  |
|xxxhdpi  |192 * 192  |


結果がこちら！！（余白までちゃんと合わせてないですが・・）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252283/890fc2a3-ff28-cc20-6a67-3e89e2df7f1d.png)

# Tips
empty画像を用意するのが面倒な場合は、fullの画像のalphaやtintを設定して色を薄くしたり変えてしまうことも可能です

MyRatingStar.xml
``` xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@android:id/background" />
        <bitmap
            android:alpha="0.5"
            android:src="@drawable/rating_empty"
            android:tint="?attr/colorControlNormal" />
    </item>
    <item
        android:id="@android:id/secondaryProgress"
        android:drawable="@drawable/rating_half" />
    <item
        android:id="@android:id/progress"
        android:drawable="@drawable/rating_full" />
</layer-list>
```