Однотипні атрибути в attrs.xml для користувацького перегляду


180

Я пишу декілька власних представлень, які мають однакові атрибути. У відповідному <declare-styleable>розділі в attrs.xmlя хотів би використовувати однакові назви для атрибутів:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyView1">
        <attr name="myattr1" format="string" />
        <attr name="myattr2" format="dimension" />
        ...
    </declare-styleable>

    <declare-styleable name="MyView2">
        <attr name="myattr1" format="string" />
        <attr name="myattr2" format="dimension" />
        ...
    </declare-styleable>
</resources>

Я отримую помилку про те , що myattr1і myattr2вже визначені. Я виявив, що я повинен опустити formatатрибут для myattr1і myattr2в MyView2, але якщо це зробити, я отримаю таку помилку в консолі:

[2010-12-13 23:53:11 - MyProject] ERROR: In <declare-styleable> MyView2, unable to find attribute 

Чи є спосіб я досягти цього, можливо, якийсь пробіг імен (просто здогадуючись)?

Відповіді:


401

Рішення. Просто витягніть загальні атрибути з обох представлень та додайте їх безпосередньо як діти <resources>вузла:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="myattr1" format="string" />
    <attr name="myattr2" format="dimension" />

    <declare-styleable name="MyView1">
        <attr name="myattr1" />
        <attr name="myattr2" />
        ...
    </declare-styleable>

    <declare-styleable name="MyView2">
        <attr name="myattr1" />
        <attr name="myattr2" />
        ...
    </declare-styleable>
</resources>

11
що відбувається, коли myattr1є рядок в MyView1і ціле число MyView2?
foxx1337

4
Я не думаю, що так, наприклад, у нас може бути атрибут "орієнтація", а для деяких - "горизонтальний" / "вертикальний", а для інших "пейзаж" / "портрет" / "квадрат". З моєї точки зору, це помилка (або, принаймні, непослідовна поведінка) в Android (майте на увазі, що: 1. стильові атрибути завжди починаються з префікса = ім'я перегляду і 2. якщо ви створюєте окремі бібліотечні проекти для таких поглядів, все буде добре )
se.solovyev

4
Коли я дотримуюся цієї відповіді, я отримую ERROR: In <declare-styleable> com_app_view_widget, unable to find attribute customAttr За всю думку, яку я намагаюся заявити. Будь-які ідеї?
Дапп

45
@Google: Crappy design
Glenn Bech

6
@ foxx1337 Просто використовуй <attr name="myattr1" format="string|integer" />. Працює для мене.
Mygod

58

Я публікую цю відповідь, оскільки вищезгадане рішення не вийшло для мене в Android Studio. Мені потрібно поділитися власними атрибутами серед своїх власних представлень, тому я спробував вищевказане рішення в Android Studio, але не пощастило. Тому я експериментую і іду способом це зробити. Сподіваюся, це може допомогти тому, хто шукає ту саму проблему.

  <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <!-- parent styleable -->
     <declare-styleable name="MyView">
         <attr name="myattr1" format="string" />
         <attr name="myattr2" format="dimension" />
     </declare-styleable>

     <!-- inheriting parent styleable -->
     <!-- also note "myBackgroundColor" belongs to child styleable"MyView1"-->
    <declare-styleable name="MyView1" parent="MyView">
        <attr name="myattr1" />
        <attr name="myattr2" />
        <attr name="myBackgroundColor" format="color"/>
    </declare-styleable>


    <!-- inheriting parent styleable -->
    <!-- same way here "myfonnt" belongs to child styelable "MyView2" -->
    <declare-styleable name="MyView2" parent="MyView">
        <attr name="myattr1" />
        <attr name="myattr2" />
        <attr name="myfont" format="string"/>
        ...
    </declare-styleable>
</resources>

Це працює для мене повністю. Нам потрібно зробити батьківський стиль, а потім нам слід успадкувати цей батьківський стиль. Наприклад, як я вже робив вище: батьківське стильове ім'я MyView і успадкувало це для інших моїх стилів, таких як MyView1 та MyView2 відповідно.


1
Це працювало для мене. Не вдалося знайти спосіб посилання на витягнуті атрибути в коді з прийнятої відповіді.
Неманья Ковачевич

Гм ... це дивно ... прийняте рішення, здається, працює добре для мене (targetSdkVersion 27). Можливо, тому, що такі атрибути, як "текст", є загальними, а можливо, існували і в інших attrs.xml ..?
Аба

Я спробував з ім'ям, яке, швидше за все, є рідкісним, і прийняте рішення все ще працювало на мене.
Аба

Я згоден з першим коментарем! Немає способу посилання на витягнутий attr з typedArray. Тому вам потрібно визначити стилізований батько
reavcn

для цього роботу не забудьте розглянути цей атрибут в батькові , а не в дитині (для класу MyView2права: R.styleable.MyView2_myattr1, неправильно: R.styleable.MyView_myattr1)
vigilancer

28

Як відповіла Прия Сінгал, Android Studio вимагає, щоб загальні імена атрибутів були визначені в межах власного імені стилю. Вони вже не можуть бути в корені.

Однак слід зазначити ще пару речей (саме тому я також додаю відповідь):

  • Загальні стилі не повинні називати те саме, що і вид. (Завдяки цій відповіді, що вказав на це.)
  • Вам не потрібно використовувати спадщину з батьком.

Приклад

Ось що я зробив у недавньому проекті, який має два власні представлення, які мають однакові атрибути. Поки користувацькі представлення все ще мають назви атрибутів і не містять a format, я все одно можу отримати доступ до них як звичайний з коду.

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- common attributes to all custom text based views -->

    <declare-styleable name="TextAttributes">
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColor" format="color"/>
        <attr name="gravity">
            <flag name="top" value="48" />
            <flag name="center" value="17" />
            <flag name="bottom" value="80" />
        </attr>
    </declare-styleable>

    <!-- custom text views -->

    <declare-styleable name="View1">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

    <declare-styleable name="View2">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

</resources>

Упорядкований приклад

Насправді мені навіть не потрібно ставити атрибути під власною назвою. Поки я визначаю їх (даю їм format) принаймні один спеціальний вид, я можу їх використовувати в будь-якому місці (без цього format). Тож це також працює (і виглядає чистіше):

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="View1">
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColor" format="color"/>
        <attr name="gravity">
            <flag name="top" value="48" />
            <flag name="center" value="17" />
            <flag name="bottom" value="80" />
        </attr>
    </declare-styleable>

    <declare-styleable name="View2">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

</resources>

Для великого проекту, однак, це може заплутатися, і визначення їх у верхній частині в одному місці може бути кращим (як тут рекомендується ).


Що не так із спадщиною? У мене є власні ієрархії подання зображень, які пов'язані стилі стилів не відображають цього взаємозв'язку, який можна вивести лише в асоційованих визначеннях стилю шляхом іменування конвенцій та визначених в них елементів (зауваживши, що декілька належать до одного стильового, а кілька - до іншого). Я вважаю за краще, щоб це було чітко з parentатрибутом, але я не бачив багатьох публікацій, які б підказували його використання
Саміс

@samis, я над цим не працював деякий час, але не знаю нічого поганого у використанні parent. Я думаю, що я просто говорив, що цього не потрібно.
Suragch

Це не потрібно, я просто створив ще один підклас, обгорнутий додатковим атрибутом, який я не хотів ставити в базовий клас. Я просто використовую коментарі та називаючи конвенції, щоб вказати на поділ.
Саміс

8

Спасибі Льюїс, у мене була та сама проблема, і ваше рішення про спадщину дало мені підказку для цього, як це зроблено нижче, і воно працює чудово. Я просто оголосив загальні атрибути вище та переписав їх у тілі стилю декларації знову, не форматуючи. Я сподіваюся, що це комусь допоможе

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- common attributes -->
     <attr name="myattr1" format="string" />
     <attr name="myattr2" format="dimension" />

 <!-- also note "myBackgroundColor" belongs to child styleable"MyView1"-->
<declare-styleable name="MyView1" >
    <attr name="myattr1" />
    <attr name="myattr2" />
    <attr name="myBackgroundColor" format="color"/>
</declare-styleable>

<!-- same way here "myfonnt" belongs to child styelable "MyView2" -->
<declare-styleable name="MyView2" parent="MyView">
    <attr name="myattr1" />
    <attr name="myattr2" />
    <attr name="myfont" format="string"/>
    ...
</declare-styleable>


1

Про всяк випадок, якщо хтось все-таки стикався з цією проблемою після випробуваного доступного рішення. Я застряг з subtitleатрибутом add з stringформатом.

Моє рішення - видалити формат.

перед:

<attr name="subtitle" format="string"/>

після:

<attr name="subtitle"/>

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