Reputation: 7550
I want both my ViewA and ViewB to have the "title" tag. But I can't put this in 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>
because of the error Attribute "title" has already been defined. Another question shows this solution:
<?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>
but in that case, R.styleable.ViewA_title
and R.styleable.ViewB_title
are not generated. I need them for reading the attributes from the AttributeSet using the following code:
TypedArray a=getContext().obtainStyledAttributes( as, R.styleable.ViewA);
String title = a.getString(R.styleable.ViewA_title);
How can I solve this?
Upvotes: 35
Views: 11913
Reputation: 49
<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>
This doesn't work。
<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>
This also doesn't work。
<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>
This was OK!!
Upvotes: 4
Reputation: 60081
Do this instead. No parent
tag needed
<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>
This is because once title
is declared in ViewA
, it doesn't need (and also can't) to be declared in again in another declare-styleable
Upvotes: 5
Reputation: 51571
The link you have posted does give you the correct answer. This is what it suggests you do:
<?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>
Now, R.styleable.ViewA_title
and R.styleable.ViewB_title
are both accessible.
If you get a chance, read through this answer: Link. Relevant quote:
You can define attributes in the top element or inside of a element. If I'm going to use an attr in more than one place I put it in the root element.
Upvotes: 53
Reputation: 28484
You need to use inheritance
<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>
In your java code
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);
Upvotes: 3