Android: Как обновить селектор (StateListDrawable) программно - PullRequest
60 голосов
/ 23 февраля 2011

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

Я могу сделать это с помощью 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".

Ответы [ 5 ]

111 голосов
/ 20 марта 2011

Вам нужно использовать отрицательное значение нужного состояния. E.g.:

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

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

8 голосов
/ 04 августа 2015

Здесь очень поздний ответ, но в случае, если у кого-то еще возникают проблемы с программной установкой 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));
6 голосов
/ 08 октября 2015

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

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

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

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

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

Вот код, который даст вам представление о состояниях.Я использую Color.Parse () для генерации целых значений для цветов, а затем передаю их этому методу для получения 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 голосов
/ 24 мая 2011

Я собираюсь ответить на ваш вопрос "Как программно обновить селектор для КНОПКИ?" предлагая переключить кнопку на 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, расположенный в папке drawable. Вот содержимое файла селектора

<?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 вместо этого.

0 голосов
/ 23 февраля 2011

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

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

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

...