Custom attributes for custom Android Component

Let’s suppose you need to create a custom view or a custom fragment.

These components could be inflated by xml or instancited programmatically.
In case they are inflated, you could have the need to pass custom attributes to define a initial state of your component.

For example : you wanted to create a custom Fragment (call it MyFragment) that manipulates a string and an integer.

#1. declare your attributes in res/attrs.xml as follow:

As you can see, each attribute requires a format, which can be one of the followings :

#2. In you layout (where you declare your fragment), add your custom attributes to your component:

There, you need to be carefull to add a new namespace :

The value of the namespace (‘options’) could be anything you want.

#3. Extract these attributes from your fragment :
If you check the Fragment API reference, the only callback where you could deal with custom attributes is the onInflate() method

As described, this callback should only be responsible for extracting the attributes :

 » all you should do here is parse the attributes and save them away. »

Let’s suppose I have a Business Object called Company

All I have to do is parsing the attributes and creating my Company BO within onInflate() method as follow:


#4. Testing
I should have started by writing in TDD but I wanted to describe the attributes definition and parsing first. The following Unit Tests will use Junit4, Mockito as well as Robolectric (tested with 2.2).

The onInflate() method needs an activity instance to properly fetch the attributes. So we will create an Activity instance first.

Our Unit Test will consist in testing that the Company BO is properly created when onInflate() method is called.

To do so, we will populate a list of attributes that we will pass as parameter to onInflate by using RoboAttributeSet;

# How about custom views ?

The previous steps remain identical (attrs.xml, extraction) for views apart from the method where the parsing occurs. Indeed, in Views, you can parse the custom attributes from the constructor itself .

# Conclusion

Creating custom components often requires custom attributes to precisely initiate that component. What is really interesting here is the ability to properly test the parsing of the attributes using RoboAttributeSet component.