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)
надеюсь, это поможет