Tuesday, May 1, 2012

Creating a Custom View That Takes Attributes

This tutorial will demonstrate how to create a custom view that will change its appearance based on a custom attribute set in the xml layout.


1. Custom Attributes

If you have used Android Views in the layout editor, you are probably already familiar with setting attributes for views. For example, for an ImageView you can set the drawable attribute to determine what graphic to draw, or the Text Attribute for a button or label to determine what text will display.

If you find yourself designing a custom view, you may want to add custom attributes to that view that affect the display or behavior. For this example we will build off of the custom view that created before, and add an attribute to change the border color.


2. Defining the Attribute

First, we need to define the attribute for setting the color for the CustomView. We do this by editing a file called attrs.xml that is located in the res->values folder. If you do not have an attrs file, right click on the values folder and select New->Android XML File. Select a type of values, and name it attrs.xml

Creating the attrs.xml file
Once the file is created, open it up to edit the XML.

We will want to edit the XML to add information that defines attributes for our previously created custom view, aptly named CustomView. We will open a "declare-styleable" tag for this custom view. The attrs.xml file should now look like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="com.androiddom.customview.CustomView">
 </declare-styleable>
</resources>

Now, we want to define the custom attribute, and its data type. The attrs.xml file should now look like this.

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="com.androiddom.customview.CustomView">
  <attr name="border_color" format="string" />
    </declare-styleable>
</resources>

You could define as many attributes as you like, but for this tutorial we will just add one.

3. Updating the Layout File

Next, we want to update the layout file of the project to take advantage of this new attribute. First, we will update the top element LinearLayout to reference the attrs.xml we created by adding the following line.

xmlns:myapp="http://schemas.android.com/apk/res/com.androiddom.customview"


And then we will reference this new attribute in our CustomView element by adding this line

myapp:border_color="#0000ff"

The entire layout file is listed below, so you can see exactly where these were inserted.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:CustomView="http://schemas.android.com/apk/res/com.androiddom.customview"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <com.androiddom.customview.CustomView
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    CustomView:border_color="#0000ff"
    />
    
</LinearLayout>

4. Updating the CustomView to Use the Attribute

Finally, we must update the CustomView.java class to take advantage of this new attribute.

In the constructor, we will first want to obtain a TypedArray of the styled attributes specific to CustomView. The code below will do this.

TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.com_androiddom_customview_CustomView);

Next, we will want to set the color of the paint based on this attribute.

paint.setColor(Color.parseColor(a.getString(R.styleable.com_androiddom_customview_CustomView_border_color)));

The newly updated constructor code is shown below.

public CustomView(Context context, AttributeSet attrs) {
 super(context, attrs);
 
 TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.com_androiddom_customview_CustomView);
 
 paint = new Paint();
 paint.setStrokeWidth(20);
 paint.setColor(Color.parseColor(a.getString(R.styleable.com_androiddom_customview_CustomView_border_color)));
 paint.setStyle(Paint.Style.STROKE);
}

And for reference, the updated code for the entire class is shown below.

package com.androiddom.customview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.ImageView;

public class CustomView extends ImageView {

 private Paint paint;
 
 public CustomView(Context context, AttributeSet attrs) {
  super(context, attrs);
  
  TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.com_androiddom_customview_CustomView);
  
  paint = new Paint();
  paint.setStrokeWidth(20);
  paint.setColor(Color.parseColor(a.getString(R.styleable.com_androiddom_customview_CustomView_border_color)));
  paint.setStyle(Paint.Style.STROKE);
 }
 
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  
  int height = this.getMeasuredHeight();
  int width = this.getMeasuredWidth();
  
  // Draw a border
  canvas.drawRect(10, 10, width-10, height-10, paint);
 }

}

5. Viewing the Results

You can now view the layout from the layout editor

Viewing the custom view from the layout editor

and run the program to see it on the emulator

Viewing the custom view from the emulator

For fun and extra practice, you could try adding a custom attribute to adjust the thickness of the border.


------------------------------------------------------------

We create these tutorials in our free time. If you like what you see please consider buying us a cup of coffee so we can keep creating useful material. Click on the image below to make a donation via Paypal.

5 comments:

  1. Currently working through all of your tutorials while trying to develop my own app. Just wanted to say thanks for the easy to read tutorials which really help a newbie like me grasp simple concepts.

    ReplyDelete
  2. Thanks for the nice comments! I am glad you have found the tutorials helpful.

    Feel free to post any suggestions for tutorials too.

    ReplyDelete
  3. Thanx for your tutorials. They let me save a lot of time - instead of surfing the net in seach of information I use your tuts.

    ReplyDelete
    Replies
    1. Thank you for your nice comments! We are glad they help. Let us know if you would like to see anything in specific, and we'll see what we can do.

      Delete
  4. thanks , finally i got it what i wanted. !!

    ReplyDelete