日々是好日

プログラミングについてのあれこれ、ムダ知識など

Androidのselectorタグの書き方について

Androidでボタンのチェック状態等でリソースを切り替えるDrawable Resourceについてメモ。

selectoritemタグの記述の仕方について小一時間ハマった。

Drawable Resourceとは

公式ドキュメント。この中でも、今回は状態リスト(StateListDrawable)について。

developer.android.com

StateListDrawable は XML 内に定義されるドローアブル オブジェクトで、オブジェクトの状態に応じて、同一のグラフィックに異なる画像を使用します。 たとえば、Button ウィジェットは複数の状態(押下状態、フォーカス状態、どちらでもない状態)をとりますが、状態リストのドローアブルを使用すると、状態に応じて異なる背景画像を使うことが可能です。

やりたいこと

今回ハマったのは、RadioGroupで囲ったRadioButtonのチェック状態の表示設定のため、 RadioButtonにStateListDrawableを設定した場合を例に書いていく。

仕様はこんな感じ。

  • RadioGroupタグ内にRadioButtonを4つ配置
  • 外枠(RadioGroup)
    • 角丸4dp(corners=4dp
    • 枠線色指定(stroke.color
    • 枠線幅指定(stroke.width=1dp
    • 塗りつぶし色指定(solid
  • 項目(RadioButton)
    • 角丸4dp(corners=4dp
    • チェック状態・未チェック状態・押下状態でそれぞれ塗りつぶし色を指定
    • チェック状態・未チェック状態でそれぞれテキスト色を指定
    • 未チェック状態は角丸を指定しない

仕上がりはこんな感じ。

f:id:kcpoipoi:20200518161623g:plain

単純に色を指定するだけなら、こちらのY.A.Mさんの記事のようにcolorタグで指定すればOK。 y-anz-m.blogspot.com

backgroundに適用するDrawable

下記のようにbackgroundshapeと塗りつぶし色を指定する場合は、solidで指定する。

<!-- drawable/toggle_background.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_selected="true" >
    <shape
      android:shape="rectangle">
      <corners android:radius="@dimen/round_corners"/>
      <solid android:color="@color/colorAssort3"/>
    </shape>
  </item>
  <item android:state_selected="false">
    <shape
      android:shape="rectangle">
      <corners android:radius="@dimen/round_corners"/>
      <solid android:color="@color/colorBase2"/>
    </shape>
  </item>
</selector>
<!-- 使用例 -->
<RadioButton
  android:background="@drawable/toggle_background"
/>

下記のようにcolorタグと併用しようとすると、先にあるタグ(この場合はcolorタグ)のみ読み込まれて、角丸がきちんと表示されないため注意。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_selected="true" >
    <color android:color="@color/colorAccent2" />
    
    <!-- shape以下は適用されない -->
    <shape
      android:shape="rectangle">
      <corners android:radius="@dimen/round_corners"/>
    </shape>
  </item>
</selector>

また、上記の書き方だとxmlが長くなりがちなので、drawableプロパティでDrawableResourceを指定する形の方が見やすくなる。

<!-- drawable/radio_checked.xml -->
<?xml version="1.0" encoding="utf-8"?>
<shape
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners android:radius="@dimen/round_corners"/>
  <solid android:color="@color/colorAssort3"/>
</shape>

<!-- drawable/radio_pressed.xml -->
<?xml version="1.0" encoding="utf-8"?>
<shape
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners android:radius="@dimen/round_corners"/>
  <solid android:color="@color/colorAccent3"/>
</shape>
<!-- drawable/toggle_background.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/radio_checked" android:state_selected="true" />
  <item android:drawable="@drawable/radio_pressed" android:state_selected="false" />
</selector>

textColorに適用するDrawable

textColorに状態リストを適用する場合も上記と同様。

ただし、backgroundと違い、こちらはitemタグのcolorプロパティで指定する必要がある。

<!-- drawable/toggle_textcolor.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:color="@color/colorBase2" android:state_checked="true"/>
  <item android:color="@android:color/darker_gray" android:state_checked="false"/>
</selector>

まとめ

要はshapesolidあるんだから、塗りつぶしはそっちを使おうねというだけ。