Saturday, May 22, 2010

Custom View with User Interaction

In my previous exercise "Draw a bitmap on View", "Draw something on a Canvas" and even "Android FaceDetector", the application output is drawn on View in onDraw method in application starting once only; without any interaction with user. In this exercise, a custom View with user interaction will be implemented. When user touch on the screen and move, a circle will be drawn.

Custom View with User Interaction

There is a customized MyView class, extends from View. The onTouchEvent(MotionEvent event) method is used to handle the user touch events; such as ACTION_MOVE, ACTION_DOWN and ACTION_UP. Then it calls invalidate() to force the view to be redraw, onDraw(Canvas canvas) will be called in turn.

AndroidViewUI.java
package com.exercise.AndroidViewUI;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class AndroidViewUI extends Activity {
public class MyView extends View {

private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

private float initX, initY, radius;
private boolean drawing = false;

public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}

public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}

public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}

private void init(){
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
paint.setColor(Color.WHITE);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}

@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
if(drawing){
canvas.drawCircle(initX, initY, radius, paint);
}
}

@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub

int action = event.getAction();
if (action==MotionEvent.ACTION_MOVE){
float x = event.getX();
float y = event.getY();

radius = (float) Math.sqrt(Math.pow(x-initX, 2) + Math.pow(y-initY, 2));

}
else if (action==MotionEvent.ACTION_DOWN){
initX = event.getX();
initY = event.getY();
radius = 1;
drawing = true;
}
else if (action==MotionEvent.ACTION_UP){
drawing = false;
}
invalidate();
return true;
}

}



/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);

MyView myView = new MyView(this);
setContentView(myView);
}


}


Download the file.

Related Article: Instance two object from the same custom view class



3 comments:

Saad us Salam said...

Hi,
Nice example. I am also working with custom views. I am getting a problem when trying to add two instances of a custom view. I also used your activity, created two instances, added those views into a table layout and set that table layout object as content view.
For some reason this doesn't work. It first gives a force close message and then onDraw for only first view is called. Second view is never displayed. Any idea what should be done?

Erik said...

Hello Saad us Salam,

I don't know the details of your case. But I tried to instance two object of the same custom view in the same screen, it seem have no problem. Ple refer to Instance two object from the same custom view class

Anonymous said...

Hi,
thanks for sharing knowledge through blog.
i am working on custom views.
i want to draw a circle and also want to drag and zoom it. any help will be appreciated
Manawar Ali