it-swarm.com.ru

Как ссылаться на атрибуты стиля из прорисовки?

Я хочу иметь 2 выбираемые темы для моего приложения. Для этого я определил некоторые атрибуты, например:

 <attr format="color" name="item_background" />

Затем я создал обе темы, например:

  <style name="ThemeA">
     <item name="item_background">#123456</item>
 </style>

 <style name="ThemeB">
     <item name="item_background">#ABCDEF</item>
 </style>

Этот метод прекрасно работает, что позволяет мне легко создавать и изменять несколько тем. Проблема в том, что кажется, что его можно использовать только в представлениях, а не в Drawables.

Например, ссылка на значение из View внутри макета работает:

 <TextView Android:background="?item_background" />

Но делать то же самое в Drawable не так:

 <shape Android:shape="rectangle">
     <solid Android:color="?item_background" />
 </shape>

Я получаю эту ошибку при запуске приложения:

    Java.lang.UnsupportedOperationException: Can't convert to color: type=0x2

Если вместо ?item_background я использую жестко закодированный цвет, он работает, но это не позволяет мне использовать мои темы. Я также попробовал ?attr:item_background, но то же самое происходит.

Как я мог это сделать? И почему это работает в представлениях, а не в Drawables? Я не могу найти это ограничение нигде в документация ...

84
MM.

По моему опыту не представляется возможным ссылаться на атрибут в формате XML.
Для создания темы вам необходимо:

  • Создайте один xml drawable для темы.
  • Включите нужный цвет в ваш рисунок, используя тег @color или формат #RGB.

Сделайте атрибут для вашего рисования в attrs.xml .

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <!-- Attributes must be lowercase as we want to use them for drawables -->
   <attr name="my_drawable" format="reference" />
</resources>

Добавьте свой drawable в ваш theme.xml .

<style name="MyTheme" parent="@Android:style/Theme.NoTitleBar">
   <item name="my_drawable">@drawable/my_drawable</item>
</style>

Ссылка на ваш drawable в макете, используя свой атрибут.

<TextView Android:background="?my_drawable" />
147
L. G.

Начиная с Lollipop (API 21) эта функция поддерживается, см https://code.google.com/p/Android/issues/detail?id=26251

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

15
marmor

Хотя невозможно ссылаться на атрибуты стиля из элементов рисования на устройствах pre-Lollipop, но это возможно для списков состояний цвета. Вы можете использовать AppCompatResources.getColorStateList (Context context, int resId) метод из библиотеки поддержки Android. Недостатком является то, что вам придется устанавливать эти списки состояний цвета программно.

Вот очень простой пример.

color/my_color_state.xml

<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
  <item Android:state_checked="true" Android:color="?colorControlActivated" />
  <item Android:color="?colorControlNormal" />
</selector>

Виджет, которому нужен список состояний цвета:

<RadioButton
  Android:id="@+id/radio_button"
  Android:text="My Radio" />

И самое главное:

ColorStateList csl = AppCompatResources.getColorStateList(context, R.color.my_color_state);    
RadioButton r = (RadioButton) findViewById(R.id.radio_button);
r.setTextColor(csl);

Ну, не самый элегантный или самый короткий путь, но это то, что делает библиотека поддержки Android, чтобы она работала на более старых версиях (до Lollipop) Android.

К сожалению, подобный метод для рисования не работает с атрибутами стиля.

4
rubo

Как заявил @marmor, теперь это поддерживается в API 21. Но для тех из нас, кому необходимо поддерживать устаревшие версии Android, вы можете использовать эту функцию. Используя библиотеку поддержки v7, вы все равно можете использовать ее в приложениях с минимальным уровнем SDK вплоть до 7. 

В AppCompatImageView в библиотеке поддержки Android v7 реализована эта функция без ошибок. Просто замените использование ImageView на AppCompatImageView.

0
Benjamin