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

Я хочу, чтобы и мои 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);

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

4 ответа

Решение

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

<?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 более чем в одном месте, я помещаю его в корневой элемент.

Сделай это вместо этого. нет 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

<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>

Это было хорошо!!

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

<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);
Другие вопросы по тегам