Categories: Android

[Android]selectorでもattributeを使いたい!

selectorを使うと、Buttonの押してる状態や、disabledの状態のときのボタンの見た目の変更ができる。

disabledのときは別画像を表示するようにしたかったのだが、動作させるとクラッシュしてしまった。

どうやらこれを見ると、selectorにattributeの値を入れてるとクラッシュしてしまうバグが有るらしい。

cf: Android Selector Drawable doesnt work with attributes

しかしattributesをなんとしても使いたい!!

というのでなんとかしたメモです。

対策

selectorで画像を変える際は通称drawableでセットしてあげないといけない。

ならば、selectorのファイル自体をテーマごとに用意して、それをattributesで指定してあげれば解決できた。

popとofficialの2つのテーマがあったとして、それぞれのdrawableのxmlを準備する。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/official_btn_plus_2x" />
    <item android:drawable="@drawable/official_btn_plus_disabled_2x" android:state_enabled="false" />
</selector>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/pop_btn_plus_2x" />
    <item android:drawable="@drawable/pop_btn_plus_disabled_2x" android:state_enabled="false" />
</selector>

いずれも通常の状態とdisable時のボタンの様子を表してます。

次に先程作成したdrawableをattributesで呼び出せるようにstyles.xmlを準備します。

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"></style>
    <style name="OfficialAppTheme" parent="AppTheme">
        <item name="btn_plus">@drawable/official_btn_plus</item>
    </style>
    <style name="PopAppTheme" parent="AppTheme">
        <item name="btn_plus">@drawable/pop_btn_plus</item>
    </style>
    <attr name="btn_plus" format="reference" />
</resources>

ここまできたら準備完了!

あとはButtonで先程作ったattributeを指定するだけ!

<ImageButton
    android:id="@+id/plus_button"
    android:background="?attr/btn_plus"
 />

これでテーマごとにボタンの画像を差し替えることができるようになります。

Rippleの場合のselector

おまけとして、rippleを適用する場合のxmlはこんな感じで定義してます。

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/color_white">
    <item>
        <selector xmlns:android="http://schemas.android.com/apk/res/android">
            <item
                android:drawable="@drawable/official_btn_plus_disabled_2x"
                android:state_enabled="false" />
            <item android:drawable="@drawable/official_btn_plus_2x" />
        </selector>
    </item>
</ripple>
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/color_white">
    <item>
        <selector xmlns:android="http://schemas.android.com/apk/res/android">
            <item
                android:drawable="@drawable/pop_btn_plus_disabled_2x"
                android:state_enabled="false" />
            <item android:drawable="@drawable/pop_btn_plus_2x" />
        </selector>
    </item>
</ripple>

rippleの場合はrippleの中でselectorを定義するのがコツ。

まとめ

selectorでattributeが使えなくて一瞬絶望しましたが、考えようによってはうまく使えたので諦めず考えて良かったです。

mogmet

View Comments

Share
Published by
mogmet
Tags: Android