views:

2242

answers:

1

How do I declare an Android UI element using XML?

+15  A: 

The Android Developer Guide has a section called Building Custom Components. Unfortunately, the discussion of XML attributes only covers declaring the control inside the layout file and not actually handling the values inside the class initialisation. The steps are as follows:

  1. Declare attributes in values\attrs.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="MyCustomView">
            <attr name="android:text"/>
            <attr name="android:textColor"/>            
            <attr name="extraInformation" format="string" />
        </declare-styleable>
    </resources>
    

Notice the use of an unqualified name in the declare-styleable tag. Non-standard android attributes need to have their type declared. Tags declared in the superclass will be available in subclasses without having to be declared.

  1. Create constructors

Since there are two constructors that use an AttributeSet for initialisation, it is convenient to create a separate initialisation method which the constructors will call.

    private void init(AttributeSet attrs){  
        TypedArray a=getContext().obtainStyledAttributes(attrs,R.styleable.MyCustomView);
        //Use a
        Log.i("test",a.getString(R.styleable.MyCustomView_android_text));
        Log.i("test",""+a.getColor(R.styleable.MyCustomView_android_textColor, Color.BLACK));
        Log.i("test",a.getString(R.styleable.MyCustomView_android_extraInformation));
        //Don't forget this
        a.recycle();
    }

R.styleable.MyCustomView is a int[] where each element is the ID of an attribute. Attributes are then retrieved from the TypedArray using various get functions. These attributes are not necessarily defined in the XML and so if the return value can't be null as a primitive is being returned, the second argument is the default value.

If you don't want to retrieve all of the attributes, it is possible to create this array manually.The ID for standard android attributes are included in android.R.attr, while attributes for this project are in R.attr.

int attrsWanted[]=new int[]{android.R.attr.text, R.attr.textColor};

Please note that you should not use anything in android.R.styleable, as per this thread it may change in the future. It is still in the documentation as being to view all these constants in the one place is useful.

  1. Use it in a layout files such as layout\main.xml

Include the namespace declaration xmlns:app="http://schemas.android.com/apk/res/com.mycompany.projectname" in the top level xml element.

<com.mycompany.projectname.MyCustomView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent"
    android:text="Test text"
    android:textColor="#FFFFFF"
app:extraInformation="My extra information";
/> 

Reference the custom view using the fully qualified name. Note that some things in this example are just silly, such as using the android:text property, while declaring custom properties for the text color and size.

Android LabelView Sample

If you want a complete example, look at the android label view sample.

LabelView.java

TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequences=a.getString(R.styleable.LabelView_text);

attrs.xml

<declare-styleablename="LabelView">
    <attrname="text"format="string"/>
    <attrname="textColor"format="color"/>
    <attrname="textSize"format="dimension"/>
</declare-styleable>

custom_view_1.xml

<com.example.android.apis.view.LabelView
    android:background="@drawable/blue"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    app:text="Blue"app:textSize="20dp"/>

This is contained in a LinearLayout with a namespace attribute: xmlns:app="http://schemas.android.com/apk/res/com.example.android.apis"

Links

Casebash
Anyone know how to make the lists continue, instead of resetting?
Casebash