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" программно.

5 ответов


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

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

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


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

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

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

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

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

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

вот некоторый код, который даст вам представление о состояниях. Я использую цвет.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;
}

Я собираюсь ответить на ваш вопрос "Как обновить селектор для кнопки программно?- предложив заменить кнопку на LinearLayout со встроенными ImageView и TextView. Для этого есть ряд преимуществ, особенно если позже вы решите настроить свои представления. Нет никакой потери функциональности в результате этого переключателя. Вы все равно сможете прикрепить те же прослушиватели событий, которые вы можете прикрепить к кнопке, но сможете избежать укладки кнопок / вкладок кошмары. Вот соответствующий код из макета.в 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) также находятся в папке drawable.

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

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

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

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

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

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


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

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

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