ColorStateListの注意点

ColorStateList を使用するときの注意点です。いくつかハマったので残しておきます。

Kenji Abe

--

ColorStateListについて

まず、ColorStateList に簡単に説明です。

res/color にxmlファイルとして定義することが出来ます。

これをButtonの android:textColor に設定することで、押したときにテキストの色を変更できます。

また、すこし別の使い方として、既存の色に android:alpha の値を設定して新たに色の定義として使用することができます。

似たようなものに StateListDrawable があります。こちらはColorではなくDrawableになります。

この ColorStateList を使ったときの注意について解説していきます。

コードから設定するとき (Android 5.x以下)

レイアウトXMLで設定するときには基本的に問題はならないですが、コードから設定するとき、且つ Android 5.x以下 の場合に注意が必要です。

例えば、以下のようにThemeのattributeを使って色を指定しているときです。 ?attr/colorPrimary の箇所ですね。これは半透明にしてます。

このとき、 ContextCompat.getColorStateList で取得して設定すると Android 5.x 以下の場合はThemeが反映されません。なので、期待している色を取得できません。

ドキュメントにも記載されていますが、23以降しかThemeが反映されません。

Starting in Build.VERSION_CODES.M, the returned color state list will be styled for the specified Context’s theme.

これを解決するには、AppCompatResources.getColorStateList を使います。これを使うとThemeが反映された状態で色を取得するので、期待する色が取得できます。

Android 5.xのサポートは減ってきてるかもですが、使用する際は気をつけてください。

Backgroundに設定する場合

これはどのAndroidバージョンでも注意が必要です。

同じく半透明にする ColorStateList を使います。

これを通常のcolorリソースと同じようにViewの android:background に設定します。

これはコンパイルエラーが起きることなく実行することができ、更にやっかいなことにバージョンによって挙動が異なります。

  • Android 10以降 => 動く(でも、問題あり)
  • Android 10未満 => クラッシュする

Android 10未満の場合はクラッシュするので、すぐ気づくことができますが、10以降の場合は半端に動くので微妙に気づきにくいです。

Android 10以降の場合は動いてるように見えるのですが、同じ ColorStateList を使用しているViewが複数あると、2つ目以降に色が設定されません。

これを解決するには Drawable リソースをちゃんと作る必要があります。res/drawable に作成して、これをBackgoundに設定すれば、問題なく動きます。

このあたり気づきにくい部分だったりするので、注意しましょう。

--

--

Kenji Abe

Programmer / Gamer / Google Developers Expert for Android, Kotlin / @STAR_ZERO