188

I have created a custom widget, and I'm declaring it in layout.xml. I have also added some custom attributes in attr.xml. However, when trying to declare these attributes in a style in styles.xml, it's giving me No resource found that matches the given name: attr 'custom:attribute'.

I have put the xmlns:custom="http://schemas.android.com/apk/res/com.my.package" in all of the tags in styles.xml, including <?xml>, <resources>, and <style>, but it still gives me the same error, that it can't find my custom XML namespace.

I can, however, use my namespace to manually assign attributes to the view in my layout.xml, so there is nothing wrong with the namespace. My issue lies in making styles.xml aware of my attr.xml.

Vertexwahn
  • 7,709
  • 6
  • 64
  • 90
Tyler
  • 19,113
  • 19
  • 94
  • 151

6 Answers6

369

I figured it out! The answer is to NOT specify the namespace in the style.

<?xml version="1.0" encoding="utf-8" ?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <style name="CustomStyle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>

        <item name="custom_attr">value</item> <!-- tee hee -->
    </style>
</resources>
Tyler
  • 19,113
  • 19
  • 94
  • 151
  • 13
    The error disappears, but my view doesn't adopt the attribute value, while it does adopt the other (non-custom) attributes. My particular attribute is an enum. Is the snippet above working for you? – Paul Lammertsma Nov 07 '11 at 10:44
  • @PaulLammertsma I'm using an enum and this doesn't seem to work for me either. If you don't have the custom namespace xmlns attribute, you can actually type in any value you like for the item name attribute and it will compile. – David Snabel-Caunt Dec 19 '11 at 08:56
  • @DavidCaunt I did eventually get [what I was working on](http://stackoverflow.com/questions/8413572/custom-truetype-font-from-xml-only/8414994#8414994) functioning. I eventually used a string for the `declare-stylable` instead of an enum. I'm not certain why enums weren't working, but this work-around was good enough for me. – Paul Lammertsma Dec 19 '11 at 15:21
  • 3
    This doesn't even compile for me, using API lvl 16. – David Miler Dec 05 '12 at 18:43
  • This way available for me, using API Level 17. I tried to remove xmlns:custom namespace declare, it still work, I describe below answer. – VinceStyling May 07 '13 at 07:05
  • 3
    While this works, I suspect that there would be a problem resolving the attributes if an attribute with the same name existed in two or more packages but with different package names. – Johann Apr 06 '15 at 08:02
  • This works for me as well, but it is quite inconsistent for attributes to be treated this way. You would think the "android:" prefix in the styles.xml should be used to match the XML namespace alias, instead of actually being a special identifier for built-in attributes. – Nick Spacek Jun 03 '15 at 14:16
  • @NickSpacek it appears its been edited for later sdk's and/or android studio. i was back in eclipse at the time of authoring – Tyler Oct 12 '15 at 16:24
44

above answer is worked for me, I tried a litte change, I declare styleable for a class in resources element.

<declare-styleable name="VerticalView">
    <attr name="textSize" format="dimension" />
    <attr name="textColor" format="color" />
    <attr name="textBold" format="boolean" />
</declare-styleable>

in declare-styleable, the name attribute referenced a class name, so I had a view class call "com.my.package.name.VerticalView", it represented this declare must be use in VerticalView or subclasses of VerticalView. so we can declare style like this :

<resources>
    <style name="verticalViewStyle">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">36dip</item>

        <item name="textSize">28sp</item>  <!-- not namespace prefix -->
        <item name="textColor">#ff666666</item>
        <item name="textBold">true</item>
    </style>
</resources>

that's why we didn't declare namespace at resources element, it still work.

VinceStyling
  • 3,707
  • 3
  • 29
  • 44
19

values/styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    ...
    <item name="defaultButtonColor">@color/red</item>
    <item name="defaultButtonHeight">@dimen/dp_100</item>
</style>

values/attrs.xml

<resources>
    <attr name="defaultButtonColor" format="reference" />
    <attr name="defaultButtonHeight" format="reference"/>
</resources>

values/colors.xml

<resources>
    <color name="red">#f00</color>
</resources>

values/dimens.xml

<resources>
    <dimen name="dp_100">100dp</dimen>
</resources>

Using

<Button
    android:layout_width="wrap_content"
    android:layout_height="?attr/defaultButtonHeight"
    android:text="Button"
    android:textColor="?attr/defaultButtonColor"
    />

enter image description here

DEMO

Linh
  • 57,942
  • 23
  • 262
  • 279
10

Styler and vince's modification worked for me. I wanted to point out that @vince's explanation may not be entirely accurate.

To test the hypothesis that the name attribute of the declare-styleable matching the name of the custom view class is allowing us to access the custom attribute without a namespace I changed the name of the declare-styleable (the custom view was named TestViewFont:

<declare-styleable name="TextViewFont2">
    <attr name="font" format="integer"/>
</declare-styleable>

I then changed the obtainStyledAttributes call in the custom view to reflect this:

TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TextViewFont2, 0, 0);

The code still ran. So I don't think it is some kind of introspection by the declare-styleable of the class it is named after.

Thus I am led to believe that any custom attributes can be used to declare a style without referring to a namespace.

Regardless, thanks for all the help guys, it resolved my issue.

Abid H. Mujtaba
  • 1,890
  • 1
  • 24
  • 20
  • Actually, attributes share the same namespace, whether they are declared in a `declare-styleable` block or not. (sorry, I can't find the reference page for this…) Except for attributes from `android` namespace, you should only indicate the attribute name. – pr-shadoko Apr 29 '16 at 08:02
5
  • Define some attributes

<declare-styleable name="refreshPullRefreshLayout">
        <attr name="refreshColors" format="reference"/>
        <attr name="refreshColor" format="reference"/>
</declare-styleable>
  • Use it in layout file like

<com.aolphn.PullRefreshLayout
     app:refreshColor="@color/main_green"
     app:refreshColors="@array/refresh_color"/>
  • Finally use it in style file

    The difference between style file and layout file is we do not add prefiex app:
<style name="refreshStyle">
    <item name="refreshColor">@color/main_green</item>
    <item name="refreshColors">@array/refresh_color</item>
</style>

Try it ,have a nice day,this works for me.

aolphn
  • 2,950
  • 2
  • 21
  • 30
2

In case it helps anybody else, my mistake was that my custom view class was calling AttributeSet.getAttributeValue e.g.

String fontName = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto", "customFont");

...which was resulting in my custom attribute not being read in for my custom view.

The fix was to use obtainStyledAttributes in my custom view:

 TypedArray styleAttrs = context.obtainStyledAttributes(attrs, R.styleable.MyTextViewStyleable);
 String fontName = styleAttrs.getString(R.styleable.MyTextViewStyleable_customFont);

A hint that this is working correctly is that you can Ctrl/Apple + click on the R.styleable.MyTextViewStyleable_customFont to get taken straight to your attrs.xml definition.

It took me a while to spot this critical difference between my code and the other examples, as the custom attribute worked fine when passed in directly through the layout XML (instead of through a style).

Dan J
  • 25,433
  • 17
  • 100
  • 173