Custom attributes

satya - Tue May 22 2012 16:05:59 GMT-0400 (Eastern Daylight Time)

If I inherit from an existing Android class

and if the class is already allowed in an xml file, they you can just use your class in its place with a default constructor and the same allowed attributes.

satya - Tue May 22 2012 16:06:34 GMT-0400 (Eastern Daylight Time)

How can I have my own custom attributes for an android custom component?

How can I have my own custom attributes for an android custom component?

Search for: How can I have my own custom attributes for an android custom component?

satya - Tue May 22 2012 19:54:57 GMT-0400 (Eastern Daylight Time)

AttributeSet api

AttributeSet api

satya - Tue May 22 2012 20:00:37 GMT-0400 (Eastern Daylight Time)

an attributeset seem to be a way to read from XML resources

an attributeset seem to be a way to read from XML resources

satya - Tue May 22 2012 20:02:25 GMT-0400 (Eastern Daylight Time)

Here is what the docs say

A collection of attributes, as found associated with a tag in an XML document

satya - Tue May 22 2012 20:02:47 GMT-0400 (Eastern Daylight Time)

So they relate to a 'tag' and not to the whole xml

So they relate to a 'tag' and not to the whole xml

satya - Tue May 22 2012 20:09:44 GMT-0400 (Eastern Daylight Time)

Understand TypedArray

Understand TypedArray

satya - Tue May 22 2012 20:11:33 GMT-0400 (Eastern Daylight Time)

TypedArray recycle

TypedArray recycle

Search for: TypedArray recycle

satya - Tue May 22 2012 21:41:55 GMT-0400 (Eastern Daylight Time)

what is attrs.xml

what is attrs.xml

Search for: what is attrs.xml

satya - Tue May 22 2012 21:43:06 GMT-0400 (Eastern Daylight Time)

Here is an example of attrs.xml


<resources>
    <declare-styleable name="ApplicationsStackLayout">
        <attr name="stackOrientation">
            <enum name="horizontal" value="0" />
            <enum name="vertical" value="1" />
        </attr>
        <attr name="marginLeft" format="dimension"  />
        <attr name="marginTop" format="dimension"  />
        <attr name="marginRight" format="dimension"  />
        <attr name="marginBottom" format="dimension"  />
    </declare-styleable>
</resources>

satya - Tue May 22 2012 21:44:18 GMT-0400 (Eastern Daylight Time)

This article may throw some light

This article may throw some light

satya - Tue May 22 2012 21:46:01 GMT-0400 (Eastern Daylight Time)

understand declare-styleable android tag

understand declare-styleable android tag

Search for: understand declare-styleable android tag

satya - Tue May 22 2012 21:48:34 GMT-0400 (Eastern Daylight Time)

Somehow this tag points to a classname

when that class is constructed the attributes are passed to it. and then you use a typed array to get them.

satya - Tue May 22 2012 21:48:49 GMT-0400 (Eastern Daylight Time)

why not the full path to the classname?

why not the full path to the classname?

satya - Tue May 22 2012 22:04:20 GMT-0400 (Eastern Daylight Time)

declare-styleable

declare-styleable

Search Google for: declare-styleable

Search Android Developers Group for: declare-styleable

Search Android Beginers Group for: declare-styleable

Search Google Code for: declare-styleable

Search Android Issues Database for: declare-styleable

satya - Tue May 22 2012 22:27:35 GMT-0400 (Eastern Daylight Time)

declare-styleable classname implied

declare-styleable classname implied

Search for: declare-styleable classname implied

satya - Tue May 22 2012 22:32:46 GMT-0400 (Eastern Daylight Time)

what are the restrictions on the declare-styleable name attribute?

what are the restrictions on the declare-styleable name attribute?

Search for: what are the restrictions on the declare-styleable name attribute?

satya - Tue May 22 2012 22:36:22 GMT-0400 (Eastern Daylight Time)

This is a reasonable ref from stackoverflow

This is a reasonable ref from stackoverflow

satya - Tue May 22 2012 22:38:26 GMT-0400 (Eastern Daylight Time)

Ok here are the restrictions on the declare-styleable name attribute


it has to be a classname minus the package
the namespace must be the entire deeply nested package minus the classname

satya - Tue May 22 2012 22:53:38 GMT-0400 (Eastern Daylight Time)

may be...I am still researching.

may be...I am still researching.

satya - Tue May 22 2012 22:55:10 GMT-0400 (Eastern Daylight Time)

Here are key facts


declare-style first
  give it a classname
  provide attributes and their types
Provide a namespace in the layout xml files
Use generated R.sytleable.your-custom-view constants in java code

satya - Wed May 23 2012 12:45:36 GMT-0400 (Eastern Daylight Time)

declare-styleable name class just a convention

declare-styleable name class just a convention

Search for: declare-styleable name class just a convention

satya - Wed May 23 2012 12:48:21 GMT-0400 (Eastern Daylight Time)

Here is a discussion of custom attributes across libraries

Here is a discussion of custom attributes across libraries

satya - Wed May 23 2012 12:51:44 GMT-0400 (Eastern Daylight Time)

No that link does ask the right question, it was related to sub packages, not libraries

No that link does ask the right question, it was related to sub packages, not libraries

satya - Wed May 23 2012 15:24:57 GMT-0400 (Eastern Daylight Time)

Here is an example of attrs.xml for api samples from android


<resources>
    <!-- These are the attributes that we want to retrieve from the theme
         in app/PreferencesFromCode.java -->
    <declare-styleable name="TogglePrefAttrs">
        <attr name="android:preferenceLayoutChild" />
    </declare-styleable>
    
    <!-- These are the attributes that we want to retrieve from the theme
         in view/Gallery1.java -->
    <declare-styleable name="Gallery1">
        <attr name="android:galleryItemBackground" />
    </declare-styleable>
    
     <declare-styleable name="LabelView">
        <attr name="text" format="string" />
        <attr name="textColor" format="color" />
        <attr name="textSize" format="dimension" />
    </declare-styleable>

    <!-- These are attributes used with 'DraggableDot' drawables in
         view/DragAndDropActivity.java and view/DraggableDot.java -->
    <declare-styleable name="DraggableDot">
        <attr name="radius" format="dimension" />
        <attr name="legend" format="string" />
        <attr name="anr">
            <enum name="none" value="0" />
            <enum name="thumbnail" value="1" />
            <enum name="drop" value="2" />
        </attr>
    </declare-styleable>

    <!-- These are the attributes that we want to retrieve for
         app/FragmentArguments.java -->

    <declare-styleable name="FragmentArguments">
        <attr name="android:label" />
    </declare-styleable>

</resources>

satya - Wed May 23 2012 15:27:52 GMT-0400 (Eastern Daylight Time)

The name of the declare-styleable appears to be arbitrary and doesn't have to be a classname


<resources>
<item type="id" name="menu_da_clear"/>
<attr name="a1" format="string"></attr>
<declare-styleable name="SomeArbitraryName">
    <attr name="a2" format="string" />
</declare-styleable>
</resources>

satya - Wed May 23 2012 15:32:00 GMT-0400 (Eastern Daylight Time)

This creates the following constants


R.attr.a1
R.attr.a2
R.styleable.SomeAttributeName
  //this is an int araay of 1
  //the first element value is same 
  //as R.attr.a2
R.styleable.SomeAttributeName_a2

satya - Wed May 23 2012 22:49:57 GMT-0400 (Eastern Daylight Time)

Here is what the generated doc says about R.attr class

Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.

This may also be a reference to a resource (in the form "@[package:]type:name") or theme attribute (in the form "?[package:][type:]name") containing a value of this type.

satya - Wed May 23 2012 22:51:30 GMT-0400 (Eastern Daylight Time)

Sorry that generated comment was about R.attr.a1

which in the above xml defined as a string.

satya - Wed May 23 2012 22:53:33 GMT-0400 (Eastern Daylight Time)

Notice how the name of the 'styleable' is arbitrary

I could have given any continuous string name in it. It doesnt have to be a classname at all. On the internet you may perceive this as a classname. But that is quite likely a convention.

In the example above the name "SomeAttributeName" doesn't point to any class. I did not even create such a class. Compiler did not seem to care.

satya - Wed May 23 2012 23:12:16 GMT-0400 (Eastern Daylight Time)

This would be wrong: Interesting


<resources>
<item type="id" name="menu_da_clear"/>
<attr name="a1" format="string"></attr>
<attr name="a2" format="dimension"/>
<declare-styleable name="SomeArbitraryName">
    <attr name="a2" format="string" />
</declare-styleable>
</resources>

satya - Wed May 23 2012 23:13:28 GMT-0400 (Eastern Daylight Time)

It will be wrong to name two attributes with the same name

even though one is under root and one is under a particular styleable section.

satya - Wed May 23 2012 23:19:58 GMT-0400 (Eastern Daylight Time)

valid android attr format types

valid android attr format types

Search for: valid android attr format types

satya - Wed May 23 2012 23:21:47 GMT-0400 (Eastern Daylight Time)

Here is the first link off of Google

Here is the first link off of Google

satya - Wed May 23 2012 23:23:34 GMT-0400 (Eastern Daylight Time)

The above link is from Bill Woody

Bill has indicated that this is in the file AttributeFormat.java

satya - Wed May 23 2012 23:23:46 GMT-0400 (Eastern Daylight Time)

AttributeFormat.java

AttributeFormat.java

Search for: AttributeFormat.java

satya - Wed May 23 2012 23:24:34 GMT-0400 (Eastern Daylight Time)

Here are the possible values


reference
string
color
dimension
boolean
integer
float
fraction
enum
flag

satya - Wed May 23 2012 23:25:54 GMT-0400 (Eastern Daylight Time)

Also note these types are case sensitive

Also note these types are case sensitive

satya - Wed May 23 2012 23:45:49 GMT-0400 (Eastern Daylight Time)

The styleable constant R.styleable.SomeAttributeName

This is an array of resource identifiers pointing to the "attribute" object identified by "attr" tag. Each such object would have name, format, etc.

satya - Wed May 23 2012 23:46:40 GMT-0400 (Eastern Daylight Time)

what is the meaning of android colon in an attribute name?

what is the meaning of android colon in an attribute name?

Search for: what is the meaning of android colon in an attribute name?

satya - Wed May 23 2012 23:52:23 GMT-0400 (Eastern Daylight Time)

This is a really nice article and most comprehensive I have seen so far?

This is a really nice article and most comprehensive I have seen so far?

satya - Wed May 23 2012 23:55:44 GMT-0400 (Eastern Daylight Time)

Looks like the documentation is in the root attrs.xml:


core/res/res/values/attrs.xml

satya - Wed May 23 2012 23:57:56 GMT-0400 (Eastern Daylight Time)

Looks like there is a concept of reuse as well


<resources>
<item type="id" name="menu_da_clear"/>
<attr name="a1" format="integer"></attr>
<declare-styleable name="SomeArbitraryName">
    <attr name="a2" format="string" />
    <attr name="a1"/>
</declare-styleable>
</resources>

satya - Wed May 23 2012 23:58:08 GMT-0400 (Eastern Daylight Time)

Notice how 'a1' is reused with out the format

Notice how 'a1' is reused with out the format

satya - Wed May 23 2012 23:58:42 GMT-0400 (Eastern Daylight Time)

if the name says 'android:some-name' then

we use the corresponding attribute from the android name space.

satya - Wed May 23 2012 23:59:22 GMT-0400 (Eastern Daylight Time)

Example


<declare-styleable name="TogglePrefAttrs">
        <attr name="android:preferenceLayoutChild" />
    </declare-styleable>

satya - Sat May 26 2012 12:50:47 GMT-0400 (Eastern Daylight Time)

Here is a name space spec


xmlns:your-ns="http://schemas.android.com/apk/res/com.example.yourpackage

satya - Sat May 26 2012 12:54:46 GMT-0400 (Eastern Daylight Time)

The specs for this name space is same as any XML namespace

this means you can pretty much indicate whatever you want. It is only convention (probably a good one) that it points to your package name.

why am I saying this? because I thought may be Android is doing something special using this name to make sure the attributes are defined on the class you have indicated. It doesn't.

satya - Sat May 26 2012 12:57:09 GMT-0400 (Eastern Daylight Time)

However for your name space give a name that is not too cryptic


xmlns:apptemplate="http://schemas.android.com/apk/res/com.ai.android.book.apptemplate2"

Either a package name or a specific classname if there are lot of custom classes. If you only have a handful of classes your package name might work as well.

satya - Sat May 26 2012 19:39:04 GMT-0400 (Eastern Daylight Time)

Apparently this is wrong


<TextView  
   android:id="@+id/text1"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Debut Text Appears here"
    apptemplate:custom_text="Custom Hello"
    />

satya - Sat May 26 2012 19:43:42 GMT-0400 (Eastern Daylight Time)

The restriction is

Android doesn't want you to add additional attributes to your class unless there is an "id" generated through "R".

Why?

Probably because, without an integer or a constant, you will be forced to write that can be brittle. Ex:


AttribSet.getValue("apptemplate:custom_text");

I know. the method names are all wrong and all, but you get the idea.

So Android wants you to define this new string reference "custom_text" as a pre-known attribute with a proper id and possibly a type (I suppose as an added convenience)

satya - Sat May 26 2012 19:44:47 GMT-0400 (Eastern Daylight Time)

If you notice I have added this to an Android view, the result is same for a custom view as well


<com.ai.android.book.apptemplate2.MyTextView
   android:id="@+id/custom_text_id"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Debut Text Appears here"
    apptemplate:custom_text="Custom Hello"
    />

satya - Sat May 26 2012 19:46:47 GMT-0400 (Eastern Daylight Time)

I can get rid of the error by doing


<resources>
<item type="id" name="menu_da_clear"/>
<attr name="a1" format="integer"></attr>
<declare-styleable name="SomeArbitraryName">
    <attr name="a2" format="string" />
    <attr name="a1"/>
    <attr name="custom_text" format="string"/>
</declare-styleable>
</resources>

satya - Sat May 26 2012 19:47:16 GMT-0400 (Eastern Daylight Time)

I don't think it matters where I add that custom_text attribute

it can be outside of a styleable or inside.

satya - Sat May 26 2012 19:56:40 GMT-0400 (Eastern Daylight Time)

what is index of an AttributeSet?

what is index of an AttributeSet?

Search for: what is index of an AttributeSet?

satya - Sat May 26 2012 20:11:26 GMT-0400 (Eastern Daylight Time)

attribute set namespace null

attribute set namespace null

Search for: attribute set namespace null

satya - Sat May 26 2012 20:28:41 GMT-0400 (Eastern Daylight Time)

Here is an example of custom attributes I am playing with


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:apptemplate="http://schemas.android.com/apk/res/com.ai.android.book.apptemplate2"    
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<com.ai.android.book.apptemplate2.MyTextView
   android:id="@+id/custom_text_id"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Debut Text Appears here"
    apptemplate:custom_text="Custom Hello"
    />    
<TextView  
   android:id="@+id/text1"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Debut Text Appears here"
    />
</LinearLayout>

satya - Sat May 26 2012 20:29:45 GMT-0400 (Eastern Daylight Time)

The following returns a good value


String namespace="http://schemas.android.com/apk/res/com.ai.android.book.apptemplate2";
String mytext = attrs.getAttributeValue(namespace, "custom_text");

satya - Sat May 26 2012 20:30:12 GMT-0400 (Eastern Daylight Time)

attrs.getAttributeCount() returns 5

attrs.getAttributeCount() returns 5

satya - Sat May 26 2012 20:36:13 GMT-0400 (Eastern Daylight Time)

The attributeset is implemented by


android.content.res.XmlBlock$Parser

satya - Sat May 26 2012 20:36:58 GMT-0400 (Eastern Daylight Time)

what is the index in the attribute set?


for(int i=0;i<attrs.getAttributeCount();i++)
{
    Log.d("bla", "value:" + attrs.getAttributeValue(i));
}

satya - Sat May 26 2012 20:37:24 GMT-0400 (Eastern Daylight Time)

This will print


value:@2130968577
value:-1
value:-2
value:Debut Text Appears here
value:Custom Hello

satya - Sat May 26 2012 20:38:27 GMT-0400 (Eastern Daylight Time)

So clearly one should use the recommended way to get your attributes

I am just playing around to see the behavior of attributeset. Of course you will see soon the right way.

satya - Sat May 26 2012 20:48:27 GMT-0400 (Eastern Daylight Time)

So what is the right way? Use Resources.Theme.obtainStyledAttributes

So what is the right way? Use Resources.Theme.obtainStyledAttributes

satya - Sat May 26 2012 21:02:00 GMT-0400 (Eastern Daylight Time)

Let's see what happened to our styleable


public static final int[] SomeArbitraryName = {
            0x7f010000, 0x7f010001, 0x7f010002
        };

what do you think the three values in this array are? well they are the identifiers for


a1
a2
custom_text

Ta...daa...

satya - Sun May 27 2012 17:45:46 GMT-0400 (Eastern Daylight Time)

So here is the pattern that is recommended


TypedArray t = ctx.obtainStyledAttributes(attrs,R.styleable.SomeArbitraryName);
mytext = t.getString(R.styleable.SomeArbitraryName_custom_text);
t.recycle();

satya - Sun May 27 2012 17:48:36 GMT-0400 (Eastern Daylight Time)

Line1 above

This method takes the incoming attribute set and a list of attribute ids as defined in the attrs.xml. this list is given as an integer array

for convenience the ADK has generated an id array when you put a few attributes under declare-styleable. This array is indicated by


R.styleable.SomeAttributeName

satya - Sun May 27 2012 17:50:43 GMT-0400 (Eastern Daylight Time)

Line2


mytext = t.getString(R.styleable.SomeArbitraryName_custom_text);

In here we are asking the typed array to give us the value of custom_text by indicating where this item is in the typed array. the place of this item in the array is indicated by the generated constant


somearbitraryname_custom_text

satya - Sun May 27 2012 17:51:35 GMT-0400 (Eastern Daylight Time)

Line2 recycle

Finally the spec says we have to indicate the completion of use of the typedarray object so that it can be recycled or its memory managed better.

satya - Tue Sep 18 2012 08:59:43 GMT-0400 (Eastern Daylight Time)

All of this research is consolidated in to an article which is at this link

All of this research is consolidated in to an article which is at this link