Every Android project contains a "res" (resources) folder, which contains a number of subfolders, including one called "layout." This is the folder where we store web layout XML files. We can only use lowercase letters, numbers, periods, and underscores in web layout XML file name.
Being able to modify behaviour of a run time component through configuration is good architecture.
Listing 1: Text view declaration in an Android layout file
<TextView
android:id="@+id/text1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Debut Text Appears here"
/>
In this example the string "android:text" is called an attribute of the class android.widget.TextView. The string "android" in "android:text" defines the XML namespace to separate our own attributes from those as defined in the android SDK. This is an example of how configuration can be used to change the behavior of a component at run time.
TextView happens to be a class that comes with the Android SDK. Android SDK has architected this class in such a way that we can change its behaviour at run time.
Listing 2: Example of TextView
<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"
/>
The attribute "custom_text" is a new attribute that is understood only by MyTextView, the class that is inherited from TextView. apptemplate is again a convention in XML to avoid attribute name conflicts. The name space becomes clear when we see the parent root XML node definition in the full xml layout file.
Listing 3: Example of layout file presenting a few lines at the top and bottom of that file.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:apptemplate="http://schemas.android.com/apk/res/com.ai.android.book.apptemplate2"
....
>
<TextView .... />
<com.ai.android.book.apptemplate2.MyTextView .... />
</LinearLayout>
Notice that the two namespaces "android" and "apptemplate" at the beginning of the XML root node LinearLayout. The namespaces have to be unique. It is a mere convention that they point to an "http" like resource identifier. It is also a convention that we distinguish the new custom name space using a structure similar to android spec and ends it with our own root package name where the custom classes reside. In this example the root java package name is:
com.ai.android.book.apptemplate2
Even if there are sub packages under this package, it is sufficient to namespace them with the root package (in the layout file), unless we feel there are too many custom classes and we want to avoid name conflicts. Then we are free to have multiple name spaces for our sub packages. We are free to choose whatever pattern that meet our needs and don't have to follow the EXACT class package structure for the namespace.
Let's see now what MyTextView implementation may look like to read this custom attribute
Listing 4: Defining MyTextView Implementation
Public class MyTextView extends TextView
{
public MyTextView(Context context) {
super(context);
setMyText(context);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setMyText(context,attrs);
}
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setMyText(context,attrs);
}
//Implementation of setMyText
private void setMyText(Context context)
{
this.setText("Hello there");
}
private void setMyText(Context context, AttributeSet attrs)
{
this.setText(getFromAttrs(context,attrs));
}
//Function to read the custom attribute
//Stubbed out for now
private String getFromAttrs(Context ctx, AttributeSet attrs)
{
String myText ="Custom Text";
return mytext;
}
}
Notice how this custom class is trying to read from the custom attribute in the method getFromAttrs().
First problem: Attribute Resource IDs and attrs.xml
So far we have a java class MyTextView. We have a layout file where we indicated a custom attribute called "custom_text".
Now if we place the layout file that has this custom attribute in our project and the compiler will tell us that the following attributeapptemplate:custom_text="Custom Hello" is in error. The error says that there is no "resource id" available for 'custom_text'.
In android when we declare resources such as strings, images, menus, and layouts in xml files Android stores them away and gives them unique integer constants called resource ids.
So to get a resource id for "custom_text", like other resources such as strings, we have to define this in an XML file.
"Custom_text" is an attribute that is going to be used again and again (like an instance). So, perhaps, we need to define it somewhere else first and possibly tell android more about this "custom_text" attribute such as, is it a string or an integer, or a boolean etc.
This definition of a custom attribute happens in an XML file sitting under the/res/values sub directory. Typically this file is called attrs.xml
Listing 5: Here is an example of custom attribute
<resources> <attr name="custom_text" format="string"></attr> </resources>
The custom attribute definitions don't have to be in attrs.xml. We can put them in strings.xml if we want, as long as this file is under the values sub directory. However, the convention is to use attrs.xml.The XML node "attr" is of special importance.
The custom attribute definition in the attrs.xml will create a resource constant like the followingR.attr.custom_text
Here is an implication of this. Because every native view/class in the android SDK may also have attributes that are defined this way, there must be an android.R.attr.* namespace that will tell us all possible attributes defined in the Android SDK!!
It is not wildly useful but if we want to know what is the "sum total" of the attributes defined by all the Android controlswe can look at the API reference for android.R.attr
Turning attention to the "format" property of the custom attribute, in my example above we have defined the custom_text as a string. This is indicated by the "format" attribute. Here are all the possible formats for XML defined object attributes.
To know how these format types are used we can see the Android API examples project which comes with the android SDK. Look at the /res/values/attrs.xml file.
Also, if we are able to get access to the source code of Core Android jar we can take a look at the "attrs.xml" in the android core project to see most of the formats used.
Listing 6: Examples of custom attributes taken from the android attrs.xml files
<attr name="text" format="string" /> <attr name="textColor" format="color" /> <attr name="textSize" format="dimension" /> <attr name="textAppearance" format="reference" /> <attr name="textColorPrimary" format="reference|color" /> <attr name="anr"> <enum name="none" value="0" /> <enum name="thumbnail" value="1" /> <enum name="drop" value="2" /> </attr> <attr name="windowSoftInputMode"> <flag name="stateUnspecified" value="0" /> <flag name="stateUnchanged" value="1" /> </attr> <!-- absolute dimension or fraction of the screen size --> <attr name="windowMinWidthMajor" format="dimension|fraction" />
Most attribute formats listed above are easy to interpret. Not so obvious in this listing is where formats can be combined as in "dimension|fraction" indicating that the value for the attribute can be either an absolute dimension or a percentage fraction.
So far we have done the following:
Listing 7: Locating the method where we are expecting to read the custom attribute
//Function to read the custom attribute
private String getFromAttrs(Context ctx, AttributeSet attrs)
{
String myText ="Custom Text";
return mytext;
}
An AttributeSet object corresponds to the set of attributes that are specified at that specific XML view object tag.
Listing 8: Following is the attribute specification for MyTextView
<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"
/>
The passed in AttributeSet object is a set of attributes that is a collection of id, layout_width, layout_height, text, and custom_text and NO MORE.
Listing 10: The AttributeSet class with the below methods
getAttributeCount(); getAttributeValue(String namespace, String name); getAttributeName(int index); getAttributeValue(int index);
For our example, the first method, getAttributeCount(), returns 5. Then using the index we can get the attribute value for our index for which our custom attribute name matches.

Figure 1: Sample Output
We understand how to create objects or attributes in Android. See you next time.







See the prices for this post in Mr.Bool Credits System below: