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


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іншими зображеннями.


чи не було б легше мати два селектори та поміняти їх?
bigstones

2
Проблема з цим полягає в тому, чи можете ви закінчити сотні XML-файлів.
Еміль

Відповіді:


244

Наскільки мені вдалося знайти (я сам намагався зробити щось подібне), немає способу змінити єдиний стан після того, як StateListDravable вже визначений. Однак ви можете визначити НОВЕ за допомогою коду:

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);

І ви можете просто тримати два під рукою або створити інший, як вам потрібно.


1
Я не зміг додати це до перегляду зображень. setState на ньому недоступний.
Краплі Юпітера

2
насправді я знайшов його, його setImageDravable () Дякую вам дуже, що він працював і врятував мене близько 40 xml файлів!
dropOfJupiter

2
Тож у мене є ще одна пов’язана з цим примітка. Я сподівався, що ти зможеш відповісти. У мене цей селектор встановлений у ImageView, який знаходиться всередині користувацького керування. Спеціальний елемент керування також має селектор як фон. Отже, селектор цілого елемента керування працює, тоді як селектор ImageView - ні. Чи є щось, що я роблю неправильно? Чи є послідовність?
Краплі Юпітера

1
Ласкаво просимо! Так, я не знаю, чому я поставив setState, має бути встановленийImageDravable, ти маєш рацію. Що стосується вашого іншого запитання, я б запропонував опублікувати нове запитання з кодом для вашого користувальницького керування та його селектора, я не впевнений у відповіді на це.
Кевін Коппок

3
я використовую той же код. завжди залишається зображення, яке я вказав у ----> new int [] {}. де я помилявся ??
KK_07k11A0585

6

У мене була така ж проблема і пішов крок далі, щоб її вирішити. Однак, єдиною проблемою є те, що ви не можете вказати NavStateListDravable в xml, тому вам доведеться встановити фон вашого елемента інтерфейсу через код. Тоді метод 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 !.


Навсталіст-код, що дозволяє відтворювати, ефективно робить селектор xml надмірним.
Еміль

Привіт, Емілі, чи існує можливість, що малюнки як фон кнопки не з'являться вперше з будь-якої причини. В даний час у мене виникає проблема, коли мені потрібно торкнутися області кнопки для відображення фону, або вимкнутись і повернутися назад до активності. (Це відбувається лише на екрані hdpi, але добре працює на mdpi). Я вважаю, що і у цієї проблеми може бути проблема. Чи перевіряється ваш код на всю щільність екрана?
ryvianstyron

Привіт, ні, це було написано досить добре, тому було лише для одного пристрою. Я не впевнений, яка проблема може виникнути, хоча, наскільки мені відомо, щільність екрана та макетів не повинні представляти проблеми.
Еміль

Дякую, я не зовсім знаю, що робив неправильно, але врешті-решт у мене було лише таке: buttonStates = new StateListDravable (); buttonStates.addState (новий int [] {statePress}, ApplicationConstants.moduleImageLoader.findImageByName (dravable_press)); buttonStates.addState (new int [] {- ​​stateFocused, -statePress, -stateSelected}, ApplicationConstants.moduleImageLoader.findImageByName (dravable_normal));
ryvianstyron

1
Це перше місце, де я бачу, що негативні значення повинні використовуватися для станів, встановлених на хибні. Документація щодо цього не дуже зрозуміла. Дякую за пораду!
eocanha
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.