Как объявить несколько стилируемых атрибутов с тем же именем для разных тегов?

Я хочу, чтобы оба объекта ViewA и ViewB имели тег "title". Но я не могу поместить это в attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ViewA">
        <attr name="title" format="string" />
    </declare-styleable>
    <declare-styleable name="ViewB">
        <attr name="title" format="string" />
        <attr name="max" format="integer" />
    </declare-styleable>
</resources>

из-за ошибки Атрибут "title" уже определен. Другой вопрос показывает это решение:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="title" format="string" />
    <declare-styleable name="ViewB">
        <attr name="max" format="integer" />
    </declare-styleable>
</resources>

но в этом случае R.styleable.ViewA_title и R.styleable.ViewB_title не генерируются. Мне нужны они для чтения атрибутов из AttributeSet, используя следующий код:

TypedArray a=getContext().obtainStyledAttributes( as, R.styleable.ViewA);
String title = a.getString(R.styleable.ViewA_title);

Как я могу это решить?

Ответы

Ответ 1

Ссылка, которую вы опубликовали, дает правильный ответ. Это то, что вы предлагаете:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="title" format="string" />
    <declare-styleable name="ViewA">
        <attr name="title" />
    </declare-styleable>
    <declare-styleable name="ViewB">
        <attr name="title" />
        <attr name="max" format="integer" />
    </declare-styleable>
</resources>

Теперь доступны R.styleable.ViewA_title и R.styleable.ViewB_title.

Если у вас есть шанс, прочитайте этот ответ: Ссылка. Соответствующая цитата:

Вы можете определить атрибуты в верхнем элементе или внутри элемент. Если я собираюсь использовать attr в более чем одно место, которое я помещаю в корневой элемент.

Ответ 2

Вам нужно использовать наследование

<resources>
    <declare-styleable name="ViewA">
        <attr name="title" format="string" />
    </declare-styleable>

    <declare-styleable name="ViewB" parent="ViewA"> // inherit from ViewA
        <attr name="min" format="integer" />
        <attr name="max" format="integer" />
    </declare-styleable>
</resources>

В вашем java-коде

String namespace = "http://schemas.android.com/apk/res/" + getContext().getPackageName();
int title_resource = attrs.getAttributeResourceValue(namespace, "title", 0); 
String title = "";
if(title_resource!=0){
  title = getContext().getString(title_resource);
}

int min = attrs.getAttributeResourceValue(namespace, "min", 0); // read int value
int max = attrs.getAttributeResourceValue(namespace, "max", 0);

Ответ 3

Сделайте это вместо этого. Нет тега parent

<resources>
    <declare-styleable name="ViewA">
        <attr name="title" format="string" />
    </declare-styleable>

    <declare-styleable name="ViewB" >
        <attr name="title" /> 
        <attr name="min" format="integer" />
        <attr name="max" format="integer" />
    </declare-styleable>
</resources>

Это связано с тем, что однажды title объявлен в ViewA, ему не нужно (а также не может) быть объявлено снова в другом declare-styleable

Ответ 4

<resources>
<declare-styleable name="ViewA">
    <attr name="title" format="string" />
</declare-styleable>

<declare-styleable name="ViewB" parent="ViewA"> // inherit from ViewA
    <attr name="min" format="integer" />
    <attr name="max" format="integer" />
</declare-styleable>

Это не работает.

<resources>
<attr name="title" format="string" />
<declare-styleable name="ViewA">
    <attr name="title" />
</declare-styleable>
<declare-styleable name="ViewB">
    <attr name="title" />
    <attr name="max" format="integer" />
</declare-styleable>

Это также не работает.

<resources>
<declare-styleable name="ViewA">
    <attr name="title" format="string" />
</declare-styleable>

<declare-styleable name="ViewB" >
    <attr name="title" /> 
    <attr name="min" format="integer" />
    <attr name="max" format="integer" />
</declare-styleable>

Это было нормально!