Я хочу иметь 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>
Этот метод отлично работает, позволяя легко создавать и изменять несколько тем. Проблема в том, что кажется, что его можно использовать только в представлениях, а не в чертежах .
Например, ссылка на значение из представления внутри макета работает:
<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
, но бывает то же самое.
Как я мог это сделать? И почему это работает в представлениях, но не в чертежах? Я не могу найти это ограничение в документации ...
Ответы:
По моему опыту, невозможно ссылаться на атрибут в XML-файле.
Для создания своей темы вам необходимо:
Включите нужный цвет в ваш рисунок прямо с
@color
тегом или в формате #RGB.Сделайте атрибут для вашего drawable в 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>
Добавьте свой чертеж в свой theme.xml .
<style name="MyTheme" parent="@android:style/Theme.NoTitleBar"> <item name="my_drawable">@drawable/my_drawable</item> </style>
Ссылайтесь на свой чертеж в макете, используя свой атрибут.
<TextView android:background="?my_drawable" />
источник
Начиная с
lollipop
(API 21) эта функция поддерживается, см. Https://code.google.com/p/android/issues/detail?id=26251Однако, если вы нацеливаетесь на устройства без леденца на палочке, не используйте его, так как он выйдет из строя, вместо этого используйте обходной путь в принятом ответе.
источник
Хотя невозможно ссылаться на атрибуты стиля из чертежей на устройствах до Lollipop , но это возможно для списков состояний цвета. Вы можете использовать метод AppCompatResources.getColorStateList (Context context, int resId) из библиотеки поддержки Android. Обратной стороной является то, что вам придется программно устанавливать эти списки состояний цвета.
Вот очень простой пример.
цвет / 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" />
И самое главное:
Что ж, не самый элегантный или кратчайший способ, но это то, что делает библиотека поддержки Android, чтобы заставить ее работать на более старых версиях (до Lollipop) Android.
К сожалению, аналогичный метод для чертежей не работает с атрибутами стиля.
источник
Я ответил на тот же вопрос в https://stackoverflow.com/a/59467269/3841352, но я также опубликую его здесь:
Я столкнулся с той же проблемой, и по состоянию на 2019 год она не была решена, поэтому вы не можете ссылаться на атрибут в селекторе как на доступный для рисования. Я поделюсь своим решением проблемы, так как я не вижу его здесь. Я нашел это в последнем комментарии отчета об ошибке .
Обходной путь - в основном создать доступный для рисования ресурс, который будет ссылаться на значение атрибута.
Чтобы проиллюстрировать ваш случай, решение будет вместо:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="?attr/colorPrimary" android:state_enabled="true" android:state_window_focused="false"/> <item android:drawable="?attr/colorPrimaryDark" android:state_pressed="true"/> <item android:drawable="@android:color/darker_gray" android:state_enabled="false"/> <item android:drawable="?attr/colorPrimary"/> </selector>
вы бы заменили? attr / * на доступный ресурс:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/colorPrimaryDrawable" android:state_enabled="true" android:state_window_focused="false"/> <item android:drawable="@drawable/colorPrimaryDarkDrawable" android:state_pressed="true"/> <item android:drawable="@android:color/darker_gray" android:state_enabled="false"/> <item android:drawable="@drawable/colorPrimaryDrawable"/> </selector>
Чертежи будут определены как:
вытяжка / colorPrimaryDrawable
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"> <solid android:color="?attr/colorPrimary" /> </shape>
вытяжка / colorPrimaryDarkDrawable
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"> <solid android:color="?attr/colorPrimaryDark" /> </shape>
Надеюсь, это поможет!!
источник
Как заявил @marmor, теперь это поддерживается в API 21. Но для тех, кому нужно поддерживать устаревшие версии Android, вы можете использовать эту функцию. Используя библиотеку поддержки v7, вы по-прежнему можете использовать ее в приложениях с минимальным уровнем SDK вплоть до 7.
В
AppCompatImageView
библиотеке поддержки Android v7 есть реализация этой функции без ошибок. Просто заменить использованияImageView
сAppCompatImageView
.источник