Як посилатись на атрибути стилю з рисунку?


96

Я хочу мати 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" />

Але робити те ж саме в Dravable не означає:

 <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, але трапляється те саме.

Як я міг це зробити? І чому це працює у поданнях, а не у малюнках? Я не можу знайти це обмеження ніде в документації ...


Це може бути дублікат наступного питання: stackoverflow.com/questions/7529574/…
Пол Ламмерцма

@ Мартін М., що ти з цим зрозумів?
user123321

Будь-яке рішення для цього ще немає? Я б’юся по тій самій стіні
Гійом

Ще одне останнє питання тут: stackoverflow.com/q/12115125/317889 Та сама проблема. Відсортуйте Google.
HGPB

3
Мабуть, ця проблема була вирішена в попередньому перегляді Android L, як зазначено тут: code.google.com/p/android/isissue/detail?id=26251
Bianca Daniciuc

Відповіді:


161

З мого досвіду, неможливо посилатися на атрибут у XML-файлі, який можна малювати.
Для того, щоб зробити свою тему вам потрібно:

  • Створіть один XML, який можна малювати за темою.
  • Додайте потрібний колір до малювання безпосередньо за допомогою @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>

Додайте малюнок до теми .xml .

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

Позначте свій малюнок у макеті, використовуючи свій атрибут.

<TextView android:background="?my_drawable" />

20
Здається, що це рішення все ж необхідне, якщо ви хочете зберегти сумісність ... Так, від L це фіксовано, а колір теми добре посилається, але той самий код працює на різних пристроях, що попередньо L, і фактично посилання attr не працює на pre-L пристрої! LoL .. Тож для мене це не встановлено, якщо мені доведеться підтримувати різні витяжні матеріали.
Давідеас

2
Я б хотів, щоб я міг підкреслити це двічі Просто спробував впорядкувати мої форми, щоб використовувати посилання замість жорсткого коду #RGB, і я отримав ту ж помилку. Прийшов до ТА за рішенням і знайшов цю саму відповідь, яку я схвалив 2 тижні тому! (facepalm)
Tiksi

2
Це супер ніндзя!
МаріусБудін

4
ARGH! Це має бути першочерговим завданням для Google, щоб здійснити виправлення подій! Позначення attr-посилання настільки надзвичайно корисне та важливе, що так близько неможливо жити, якщо у вас є кілька тем у програмі. Зараз я маю зробити три видимих ​​XML-файли для кожного з користувацьких типів кнопок!
Стефан Геннінгсен

2
Ось я хочу. дуже просте і приємне рішення в <21 SDK.
Аднан Абдолла Закі

20

Починаючи з lollipop(API 21) ця функція підтримується, див. Https://code.google.com/p/android/isissue/detail?id=26251

Однак якщо ви орієнтуєтесь на пристрої без льодяника, не використовуйте його, оскільки він вийде з ладу, використовуйте замість цього рішення у прийнятій відповіді.


Чи є можливість скористатися типом бібліотеки підтримки, щоб змусити її працювати за допомогою попередніх API?
Іван

2
Ні, бібліотека підтримки - це набір API, які можна використовувати на старих пристроях, ця зміна поведінки полягає в компіляторі та інструментах побудови, тому вона не пов’язана з бібліотекою підтримки.
мармур

3
Ні, у льодянику це була не реалізована функція, а кричуща виправлена ​​помилка. І серйозна помилка в цьому.
Адріан Сікару

чорт, я думав, що у мене є приємне тематичне рішення. тепер я повинен повернутися назад і створити купу кнопок селектора кнопок.
filthy_wizard

4

Хоча неможливо посилатись на атрибути стилю з рисунків на пристроях до Lollipop , але це можливо для списків кольорів. Можна використовувати метод AppCompatResources.getColorStateList (контекст контексту, 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.

На жаль, подібний метод для малювальних матеріалів не працює з атрибутами стилю.


1

Я відповів на те саме питання на 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>

Малюнки будуть визначені як:

drawable / colorPrimaryDrawable

<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle">
    <solid android:color="?attr/colorPrimary" />
</shape>

малювальний / кольоровийPrimaryDarkDravable

<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle">
    <solid android:color="?attr/colorPrimaryDark" />
</shape>

Сподіваюся, це допомагає !!


0

Як заявив @marmor, це зараз підтримується в API 21. Але для тих, кому нам потрібно підтримувати застарілі версії Android, ви можете використовувати цю функцію. Використовуючи бібліотеку підтримки v7, ви все ще можете використовувати її в додатках з мінімальним рівнем SDK аж до 7.

У AppCompatImageViewбібліотеці підтримки Android v7 реалізована ця помилка. Просто замінити використання ImageViewз AppCompatImageView.


2
Звучить надією! Але проблема полягає в тому, що форма Dravable не є видом. У мене є подання appcompat, що посилається на (як фон) форму, яка використовує attr для отримання тематичного кольору, і вона перетворюється на вищевказану помилку на <21. Чи є додаток для малювання, який я пропустив?
NeilS

Android 5.0.1 jy Huawei все ще постраждав.
соутертон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.