プログラムでセレクター画像を置き換える


116

セレクターに設定された描画可能な画像リソースを持つImageViewがあります。プログラムでセレクターにアクセスして、強調表示された状態と強調表示されていない状態の画像を変更するにはどうすればよいですか?

これはセレクターのコードです:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/iconSelector">
  <!-- pressed -->
  <item android:state_pressed="true" android:drawable="@drawable/btn_icon_hl" />
  <!-- focused -->
  <item android:state_focused="true" android:drawable="@drawable/btn_icon_hl" />
  <!-- default -->
  <item android:drawable="@drawable/btn_icon" />
</selector>

他の画像btn_icon_hlと入れ替えたいですbtn_icon


2つのセレクターを用意してそれらを交換する方が簡単ではないでしょうか。
bigstones

2
それに関する問題は、何百ものxmlファイルになってしまうことです。
エミール

回答:


244

私が見つけた限り(私自身も同様のことを試みました)、StateListDrawableが既に定義されている後で単一の状態を変更する方法はありません。ただし、コードを使用して新しいものを定義できます。

StateListDrawable states = new StateListDrawable();
states.addState(new int[] {android.R.attr.state_pressed},
    getResources().getDrawable(R.drawable.pressed));
states.addState(new int[] {android.R.attr.state_focused},
    getResources().getDrawable(R.drawable.focused));
states.addState(new int[] { },
    getResources().getDrawable(R.drawable.normal));
imageView.setImageDrawable(states);

また、2つを手元に置いておくことも、必要に応じて別の1つを作成することもできます。


1
これをイメージビューに追加できませんでした。setStateは使用できません。
dropsOfJupiter、2011年

2
実際、私はそれを見つけました、そのsetImageDrawable()機能してくれてありがとう、約40のxmlファイルを保存してくれました!
dropsOfJupiter

2
だから私はこれに関連する別のメモがあります。あなたが答えられることを望んでいました。カスタムセレクター内のImageViewにこのセレクターを設定しています。カスタムコントロールには、背景としてセレクタもあります。したがって、コントロール全体のセレクタは機能しますが、ImageViewセレクタは機能しません。私が間違っていることはありますか?シーケンスはありますか?
dropsOfJupiter、2011年

1
どういたしまして!ええ、なぜ私がsetStateを設定したのかわかりません。setImageDrawableにする必要があります。そうです。他の質問と同様に、カスタムコントロールのコードとそのセレクターを使用して新しい質問を投稿することをお勧めします。その答えはわかりません。
Kevin Coppock、2011年

3
私は同じコードを使用しています。----> new int [] {}状態で指定した画像は常に残ります。どこが間違っていましたか?
KK_07k11A0585

6

私は同じ問題を抱えており、それを解決するためにさらに一歩進んだ。ただし、唯一の問題は、NavStateListDrawableをxmlで指定できないため、コードを介してUI要素の背景を設定する必要があることです。次に、メインのドローアブルのレベルが変更されるたびに、子レベルリストのレベルも更新するように、onStateChangeメソッドをオーバーライドする必要があります。

NavStateListDrawableを作成するときは、表示するアイコンのレベルを渡す必要があります。

public class NavStateListDrawable extends StateListDrawable {

    private int level;

    public NavStateListDrawable(Context context, int level) {

        this.level = level;
        //int stateChecked = android.R.attr.state_checked;
        int stateFocused = android.R.attr.state_focused;
        int statePressed = android.R.attr.state_pressed;
        int stateSelected = android.R.attr.state_selected;

        addState(new int[]{ stateSelected      }, context.getResources().getDrawable(R.drawable.nav_btn_pressed));
        addState(new int[]{ statePressed      }, context.getResources().getDrawable(R.drawable.nav_btn_selected));
        addState(new int[]{ stateFocused      }, context.getResources().getDrawable(R.drawable.nav_btn_focused));

        addState(new int[]{-stateFocused, -statePressed, -stateSelected}, context.getResources().getDrawable(R.drawable.nav_btn_default));


    }

    @Override
    protected boolean onStateChange(int[] stateSet) {

        boolean nowstate = super.onStateChange(stateSet);

        try{
            LayerDrawable defaultDrawable = (LayerDrawable)this.getCurrent();


            LevelListDrawable bar2 =  (LevelListDrawable)defaultDrawable.findDrawableByLayerId(R.id.nav_icons);
            bar2.setLevel(level);
        }catch(Exception exception)
        {

        }

        return nowstate;
    }
}

さまざまなナビゲーションボタンの描画可能な状態のすべてについて、次のようなものがあります。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

   <item android:drawable="@drawable/top_bar_default" >

   </item>

    <item android:id="@+id/nav_icons" android:bottom="0dip">
        <level-list xmlns:android="http://schemas.android.com/apk/res/android">
            <item android:maxLevel="0" >
                <bitmap
                    android:src="@drawable/top_bar_icon_back"
                    android:gravity="center" />
            </item>
            <item android:maxLevel="1" >
                <bitmap
                    android:src="@drawable/top_bar_icon_nav"
                    android:gravity="center" />
            </item>
            <item android:maxLevel="2" >
                <bitmap
                    android:src="@drawable/top_bar_icon_settings"
                    android:gravity="center" />
            </item>
            <item android:maxLevel="3" >
                <bitmap
                    android:src="@drawable/top_bar_icon_search"
                    android:gravity="center" />
            </item>
        </level-list>

    </item>

</layer-list>

私はこれを質問と回答として投稿するつもりでしたが、あなたがまさに質問したように見て、ここに行きます。これにより、多くのxmlファイル定義の手間が省けます。約50〜100のxml定義から約4に下がりました。


navstatelistdrawableコードは、セレクターxmlを効果的に冗長にします。
エミール、

こんにちは、エミリー。ボタンの背景としてのドローアブルが何らかの理由で初めて表示されない可能性はありますか?現在、背景が表示されるようにボタンの領域をタッチするか、切り替えてアクティビティに戻る必要があるという問題が発生しています。(これはhdpi画面でのみ発生しますが、私のmdpiでは正常に動作します)。他の人もこの問題を抱えていると思います。コードはすべての画面密度でテストされていますか?
ryvianstyron 2012年

こんにちは、いいえ、これはフェアに書かれたもので、当時は1つのデバイスのみでした。複数の画面密度とレイアウトで問題が発生しないことを知っている限り、どのような問題が発生するかはわかりません。
エミール

ありがとう、私は何が間違っていたのかよくわかりませんが、最終的には次のようになりました:buttonStates = new StateListDrawable(); buttonStates.addState(new int [] {statePressed}、ApplicationConstants.moduleImageLoader.findImageByName(drawable_pressed)); buttonStates.addState(new int [] {-stateFocused、-statePressed、-stateSelected}、ApplicationConstants.moduleImageLoader.findImageByName(drawable_normal));
ryvianstyron

1
これは、falseに設定された状態に負の値を使用する必要があることを最初に確認した場所です。ドキュメントはそれについてあまり明確ではありません。先端をありがとう!
eocanha 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.