Подтвердить что ты не робот

Android: как программно обновить селектор (StateListDrawable)

Я хочу программно изменить селектор кнопки.

Я могу сделать это с помощью xml файла, который приведен ниже

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:state_enabled="false"
         android:drawable="@drawable/btn_off" />
   <item android:state_pressed="true"
         android:state_enabled="true" 
         android:drawable="@drawable/btn_off" />
   <item android:state_focused="true"
         android:state_enabled="true" 
         android:drawable="@drawable/btn_on" />
   <item android:state_enabled="true" 
         android:drawable="@drawable/btn_on" />
</selector>

Я хочу сделать то же самое программно. Я пробовал что-то вроде приведенного ниже

private StateListDrawable setImageButtonState(int index)
{
    StateListDrawable states = new StateListDrawable();

    states.addState(new int[] {android.R.attr.stateNotNeeded},R.drawable.btn_off); 
    states.addState(new int[] {android.R.attr.state_pressed, android.R.attr.state_enabled},R.drawable.btn_off);
    states.addState(new int[] {android.R.attr.state_focused, android.R.attr.state_enabled},R.drawable.btn_on);
    states.addState(new int[] {android.R.attr.state_enabled},R.drawable.btn_on);

    return states;
}

но он не работал.

И как программно установить android:state_enabled="false" или android:state_enabled="true".

Спасибо заранее.

4b9b3361

Ответ 1

Вам нужно использовать отрицательное значение необходимого состояния. Например:.

states.addState(new int[] {-android.R.attr.state_enabled},R.drawable.btn_disabled);

Обратите внимание на знак "-" перед android.R.attr.state_enabled.

Ответ 2

Очень поздний ответ здесь, но в случае, если у кого-либо возникают проблемы с программным обеспечением StateListDrawable. Тогда, как и в XML файлах, порядок, в котором вы устанавливаете состояния в StateListDrawable, важен.

Например, это будет работать как ожидалось:

StateListDrawable sld = new StateListDrawable();
sld.addState(new int[] { android.R.attr.state_pressed }, new ColorDrawable(Color.GRAY));
sld.addState(new int[] {}, new ColorDrawable(Color.GREEN));

Это не будет:

StateListDrawable sld = new StateListDrawable();
sld.addState(new int[] {}, new ColorDrawable(Color.GREEN));
sld.addState(new int[] { android.R.attr.state_pressed }, new ColorDrawable(Color.GRAY));

Ответ 3

Недостаточно комментариев для комментариев, но принятый ответ не помог мне.

Моя цель состояла в том, чтобы дизайнеры установили разрешенные, отключенные и нажатые цвета фона на некоторой кнопке. Я намеревался использовать их для проверки цветов на разных дисплеях.

Я заметил, что некоторые другие люди упомянули, что это тоже не сработало для них.

Состояние, которое необходимо определить,

  • не нажата и не включена, это то, что вы видите, когда кнопка включена и не нажата.
  • нажата и включена, это то, что вы видите, когда кнопка нажата и включена.
  • не включен. Это то, что вы видите, когда кнопка отключена.

Вот какой код, который даст вам представление о состояниях. Я использую Color.Parse() для генерации ints для цветов, затем передаю их этому методу, чтобы получить StateListDrawable.

private StateListDrawable createDrawable(int enabled, int pressed, int disabled) {
  StateListDrawable stateListDrawable = new StateListDrawable();

  stateListDrawable.addState(new int[] { -android.R.attr.state_pressed, android.R.attr.state_enabled }, new ColorDrawable(enabled));
  stateListDrawable.addState(new int[] { android.R.attr.state_pressed, android.R.attr.state_enabled }, new ColorDrawable(pressed));
  stateListDrawable.addState(new int[] { -android.R.attr.state_enabled }, new ColorDrawable(disabled));

  return stateListDrawable;
}

Ответ 4

Я собираюсь ответить на ваш вопрос "Как программно обновить селектор для BUTTON?" предлагая переключить кнопку для LinearLayout со встроенными ImageView и TextView. Для этого есть ряд преимуществ, особенно если позже вы решите настроить свои представления. В результате этого коммутатора нет потери функциональности. Вы по-прежнему сможете присоединять тех же прослушивателей событий, которые вы можете прикрепить к кнопке, но сможете избежать кошмаров кнопок/вкладок. Вот соответствующий код из layout.xml

    <LinearLayout 
        android:id="@+id/button"
        style="@style/ButtonStyle">
        <ImageView 
            android:id="@+id/background"
            android:src="@drawable/custom_image"/>
        <TextView 
            style="@style/TextStyle"
            android:text="Custom Button"
            android:id="@+id/text"/>
    </LinearLayout> 

Затем у меня есть селекторный файл с именем custom_image.xml, расположенный в папке с возможностью переноса. Вот содержимое селекторного файла

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/disabled_img"     android:state_enabled="false" />
    <item android:drawable="@drawable/unselected_img"     android:state_selected="false" />
    <item android:drawable="@drawable/selected_img"     android:state_selected="true" />
</selector>

Три файла исходного изображения (disabled_img.png, unselected_img.png, selected_img.png) также находятся в папке с возможностью переноса.

Теперь вернемся к вашему Java-коду. Нет необходимости в фанк-муке StateListDrawable по многим причинам. Во-первых, он просто выглядит уродливым, и его трудно поддерживать. Но самое главное, это противоречит принципам сохранения вашей логики отдельно от вашей презентации. Если вы управляете своими доступными ресурсами в Java-коде, вы знаете, что делаете что-то фундаментально неправильно.

Вот что я предлагаю вместо этого. Всякий раз, когда вы хотите, чтобы ваша кнопка была выбрана, вы просто вставляете этот однострочный шрифт:

((LinearLayout)findViewById(R.id.button)).setSelected(true);

Или, когда вы хотите, чтобы кнопка находилась в отключенном состоянии, вот еще один лайнер:

((ImageView)findViewById(R.id.background)).setEnabled(false);

Обратите внимание, что в этом последнем примере я указываю отключенное состояние в ImageView внутри LinearLayout. По какой-то причине, когда вы меняете состояние включения/отключения LinearLayout, селектор не запускается. Он отлично работает, когда вы делаете это на ImageView.

Ответ 5

Я не знаю, как вы добавляете StateListDrawable, так как кода здесь нет. Но обязательно проверьте документацию и добавьте setState().

Вы можете установить свойства из представления, например yourView.setEnabled(true)

Я надеюсь, что это поможет