Home > Programming / tutorials > Creating a Custom Widget in android

Creating a Custom Widget in android

January 20th, 2011 Leave a comment Go to comments

Apart from using text box buttons and widgets provided in android widget tool kit we can create custom UI that suits the user needs. In this post , I will explain how to to create a custom widgetstep by step.

Custom views can be created by using two classes “View” and “SurfaceView”. Both classes are used exactly the same way, but surface encapsulated by SurfaceView supports OpenGL ES library (Using OpenGL we can draw 2D and 3D objects). Also, all application views run in the main application thread, whenever you want to update View’s UI rapidly the code blocks the GUI thread.  But SurfaceView can update from the background thread. Thus SurfaceView is most commonly used in gaming and applications with heavy graphics.

To start drawing custom widgets 3basic drawing components are required

1)    Canvas : provides surface for drawing your widgets

2)    Paint: While physically drawing a picture we make use of paint brushes of different sizes and different brushes for different colors. Similarly Paint object is used to draw widgets of different colors and textures.

3)    Bitmap: Bitmap is the surface under the canvas. It holds the raw pixel values of the images draw on the canvas. While drawing on the canvas we do not color individual pixels we draw upon continuous area, the corresponding pixel values are then placed on the Bitmap.

Apart from this developers are provided with different methods to draw on the canvas.

Some of the commonly used methods are described below:

1)    drawCircle: draws circle on the canvas.

2)    drawRect: to draw a rectangle on the  canvas.

3)    drawLine: Draws a line on the canvas.

4)    drawOval: Draws an oval bounded by specified rectangle.

5)    drawBitmap: to draw bitmap on the canvas.

6)    drawPicture: to draw picture object within specified rectangle.

7)    drawText: Draws a string on the canvas.

Now lets start creating over own widgets.

Step 1: Create a View class.

public class MyView extends View{

}

Step 2: Your class may require 3 different constructors. So lets create it.

public class MyView extends View{

//constructor 1 required for in-code creation

public MyView(Context context){

super(context);

}

//constructor 2 required for inflation from resource file

public MyView(Context context, AttributeSet attr){

super(context,attr);

}

//constructor 3 required for inflation from resource file

public MyView(Context context, AttributeSet attr, int defaultStyles){

super(context, attr, defaultStyles);

}

}// End of View class – MyView

Step 3: It is very essential to define the area of your drawing surface. How will you know the height and width of your View? How will your view adapt to different screen sizes and boundaries?

Just override a method called onMeasure to determine the height and width that your view can occupy

@Override

protected void onMeasure(int widthSpec, int heightSpec)

{

int measuredWidth = MeasureSpec.getSize(widthSpec);

int measuredHeight = MeasureSpec.getSize(heightSpec);

/*measuredWidth and measured height are your view boundaries. You need to change these values based on your requirement E.g.

if you want to draw a circle which fills the entire view, you need to select the Min(measuredWidth,measureHeight) as the radius.

Now the boundary of your view is the radius itself i.e. height = width = radius. */

/* After obtaining the height, width of your view and performing some changes you need to set the processed value as your view dimension by using the method setMeasuredDimension */

setMeasuredDimension( measuredWidth, measuredHeight);

/* If you consider drawing circle as an example, you need to select the minimum of height and width and set that value as your screen dimensions

int d=Math.min(measuredWidth, measuredHeight);

setMeasuredDimension(d,d); */

}

Step 4: Now that we know the dimensions of our view lets start drawing by overriding a method called onDraw(). In the below code we will display a string in the center.

@Override

protected void onDraw(Canvas canvas){

//get the size of your control based on last call to onMeasure

int height = getMeasuredHeight();

int width = getMeasuredWidth();

// Now create a paint brush to draw your widget

Paint mTextPaint=new Paint();

mTextPaint.setColor(Color.GREEN);

// set’s paint’s text size

mTextPaint.setTextSize(40);

// Define the string you want to paint

String displayText= “My First Widget”;

// Measure width of your text string

Float textWidth = mTextPaint.measureText(displayText);

//Find the center

int px= width/2;

int py=height/2;

// Draw the string in the center of the control

canvas.drawText(displayText, px-textWidth/2, py, mTextPaint);

}

Step 5: With step 4 we have successfully created our widget. Now how do we display it? To do that we need to get the window by using Activity class and define the position of our view in the window using a Layout.

Place the following code in your layout XML file.

<com.example.MyView

android:id=“@+id/surface”

android:layout_width=“fill_parent”

android:layout_height=“fill_parent”

android:focusable=“true”

android:focusableInTouchMode=“true”

android:layout_weight=“1”/>

com.example.MyView is the name of your class along with its package.

E.g You can place your custom view between two buttons as shown below

<?xml version=“1.0” encoding=“utf-8″?>

<LinearLayout android:id=“@+id/LinearLayout01″ android:layout_width=“fill_parent” android:layout_height=“fill_parent” xmlns:android=“http://schemas.android.com/apk/res/android”>

<Button android:text=“Button” android:id=“@+id/Button” android:layout_width=” fill_parent” android:layout_height=“wrap_content”></Button>

<com.example.MyView

android:id=“@+id/surface”

android:layout_width=“fill_parent”

android:layout_height=“fill_parent”

android:focusable=“true”

android:focusableInTouchMode=“true”

android:layout_weight=“1”/>

<Button android:text=“Button” android:id=“@+id/Button” android:layout_width=” fill_paren” android:layout_height=“wrap_content”></Button>

</LinearLayout>

Now you can display this layout using an activity class as shown below

public class MyActivity extends Activity {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.myLayout);

//myLayout is the name of your Layout

}

}

If you are programmatically creating a Layout you can add your custom view by passing an instance of your view class as shown below.

public class MyActivity extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

LinearLayout layout= new LinearLayout(this);

Button but1 = new Button(this);

MyView custom_view = new MyView(this);

Button but2 = new Button(this);

layout.addView(but1);

layout.addView(custom_view);

layout.addView(but2);

setContentView(layout);

}

}

Finally output of the above code will look as shown below

Below screen shots serve as examples for custom view

SNAKE GAME

Categories: Programming / tutorials Tags:
  1. Ajay
    July 11th, 2011 at 08:47 | #1

    @Parth
    To remove the mentioned XML error you need to add the below line inside tag
    xmlns:android=”http://schemas.android.com/apk/res/android”.

  2. Parth
    June 13th, 2011 at 04:50 | #2

    When I Follow the step:5 and put the code as you suggested I got the following problem in my xml file

    Multiple annotations found at this line:
    – Open quote is expected for attribute “android:id” associated with an
    element type “com.example.CustomWidget.MyView”.
    – error: Error parsing XML: not well-formed (invalid token)

    com.example.CustomWidget is the name of my package and MyView is the class where i made my Custom Widget
    Please Help Meee…

  3. ZooL
    March 22nd, 2011 at 07:43 | #3

    Nice tutorial :)
    i have a question.. how i want to make the text size change when i click the button?

  1. January 21st, 2011 at 01:34 | #1