Заменить селекторные изображения программно

У меня есть 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 на другие изображения.

Ответ 1

Насколько я смог найти (я тоже пытался сделать что-то подобное), нет способа изменить одно состояние после того, как StateListDrawable уже определен. Однако вы можете определить NEW через код:

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

У меня была такая же проблема, и я сделал еще один шаг для ее решения. Однако единственная проблема заключается в том, что вы не можете указать NavStateListDrawable в xml, поэтому вам нужно установить фон вашего элемента пользовательского интерфейса через код. Затем метод onStateChange должен быть переопределен, чтобы гарантировать, что каждый раз, когда изменяется уровень основного drawable, вы также обновляете уровень списка дочерних уровней.

При построении 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!.