Friday, March 9, 2012

Creating a Simple Custom Android View

This tutorial will show you how to create an extremely simple custom view that draws a red border, and add this view to a layout.


1. Why Create a Custom View?

You may be wondering why you would ever want to create a custom view. Android comes with many views already, and these views follow behaviors that the user expects and has grown accustomed to (buttons, check boxes, text inputs). These views are fine and work great, but sometimes they do not provide all the functionality that your apps requires, or you may simply wish to build a more customizable component.


Views make it easy to add event listeners, use in the layout editor, and reuse in your current application or even share across projects.

For this tutorial we will be creating a view that draws a red border along its edges. This view itself may not be extremely useful, but it provides a simple introduction to custom views.

Start out with creating the typical "Hello World" project for Android.

2. Creating the View

One of the easiest ways to create a view is to extend an existing one. For this example, we will be extending the ImageView with a class called CustomView.

We will add a constructor that takes a context, and an attribute set. This will allow us to pass along attributes from the layout xml.

public class CustomView extends ImageView {

 public CustomView(Context context, AttributeSet attrs) {
  super(context, attrs);
 }
}

Since we will be drawing a border, we will need to create a paint to use. We will save the paint as an instance variable, and create the paint inside of the constructor.

The updated code for the class is listed below.

import android.content.Context;
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 static Paint paint;
 
 public CustomView(Context context, AttributeSet attrs) {
  super(context, attrs);
  
  paint = new Paint();
  paint.setStrokeWidth(20);
  paint.setColor(Color.RED);
  paint.setStyle(Paint.Style.STROKE);
 }
}

3. Overriding the onDraw Method

Next, we will override the onDraw method of the view so that we can draw our red border.

First, we will call the super class method. This will perform the normal onDraw functionality of the ImageView.

Next, we need to draw the border. To know how big to make the border we must get the bounds of the view. Finally, we use the canvas object to draw the border. We have offsets of 10 to make up for the fact that the paint has a strokeWidth of 20. This means that the paint will extend 10 pixels on either side of where we draw.

The complete and final code for the view is listed below.

package com.androiddom.customview;

import android.content.Context;
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 static Paint paint;
 
 public CustomView(Context context, AttributeSet attrs) {
  super(context, attrs);
  
  paint = new Paint();
  paint.setStrokeWidth(20);
  paint.setColor(Color.RED);
  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);
 }

}

4. Adding the View to a Layout

The easiest way to add the view is by directly editing the layout xml. Specify the full name of the class, and provide the height and width.

The full code for the layout Main.xml is listed below.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    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" 
    />
    
</LinearLayout>


Save the layout and switch back to the graphical layout to see a preview of what your custom view will look like.

Custom View in Layout Editor

5. Seeing the View in Action

Run your program to see your view in action.

The Android Custom View in the Emulator

In the future we will be re-visiting custom views in more advanced tutorials.

2 comments:

  1. How can I programmatically set the layout_width, layout_height, and adjustViewBounds values with this approach?

    ReplyDelete
  2. customDrawingView.post(new Runnable() {
    @Override
    public void run() {
    View view_instance = customDrawingView;
    android.view.ViewGroup.LayoutParams params = view_instance
    .getLayoutParams();
    int newLayoutWidth = customDrawingView
    .getWidth()
    + customDrawingView.getWidth();
    params.width = newLayoutWidth;
    view_instance.setLayoutParams(params);
    screenWidthBackup = params.width;
    }
    });

    ReplyDelete