I'm developing a draw view with multiple rectangles which can be re-sized and dragged (on a camera preview). I think I got it to work. But the thing is, the rectangles appeared to be get deleted some how. they sometimes disappear from the view and get removed from the Rect array while dragging or resizing. Can somebody point out the bug?? thanks in advanced.
here is my DrawView class
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
import android.view.SurfaceView;
public class DrawView extends SurfaceView {
private Paint textPaint = new Paint();
private List<Rect> Rectangles;
private float x_axis;
private float y_axis;
private boolean found;
private String TAG="DrawView";
private Rect tempRect;
public DrawView(Context context) {
super(context);
// Create out paint to use for drawing
textPaint.setARGB(255, 200, 0, 0);
textPaint.setStyle(Paint.Style.STROKE);
textPaint.setColor(Color.RED);
textPaint.setStrokeWidth(3);
textPaint.setAlpha(200);
/* This call is necessary, or else the
* draw method will not be called.
*/
Rectangles=new ArrayList<Rect>();
setWillNotDraw(false);
}
public void setCoordinates (float x1, float y1) {
x_axis=x1;
y_axis=y1;
Rectangles.add(new Rect(Math.round(x_axis)-150, Math.round(y_axis)-70, Math.round(x_axis)+150, Math.round(y_axis)+70));
// indicate view should be redrawn
postInvalidate();
}
public void tryDrag(float x, float y){
if(tempRect!=null){
tempRect.set(Math.round(x-tempRect.width()/2),Math.round(y+tempRect.height()/2)
,Math.round(x+tempRect.width()/2),Math.round(y-tempRect.height()/2));
postInvalidate();
}
}
public void DrawNow(){
postInvalidate();
}
public void animateDrag(float x, float y){
found=false;
tempRect=null;
for(Rect R: Rectangles){
if(R.contains(Math.round(x), Math.round(y))){
found=true;
tempRect =R;
break;
}
}
if(found){
Log.d(TAG, "inside a rectange");
}
}
public void doScale(float x, float y){
if(tempRect!=null){
int tempWidth=Math.round((tempRect.width()*x)/2);
int tempHeight=Math.round((tempRect.height()*y)/2);
tempRect.set(tempRect.centerX()-tempWidth,tempRect.centerY()+tempHeight,tempRect.centerX()+tempWidth,tempRect.centerY()-tempHeight);
postInvalidate();
}
}
@Override
protected void onDraw(Canvas canvas){
// A Simple Text Render to test the display
for(Rect R: Rectangles)
canvas.drawRect(R.left,R.top,R.right,R.bottom, textPaint);
}
}
here is my code part from the Activity class
private float scaleFactorY;
private float scaleFactorX;
@Override
public boolean onTouchEvent(MotionEvent event){
mScaleDetector.onTouchEvent(event);
if(mScaleDetector.isInProgress()) return false;
//let the ScaleGestureDetector try first
// if scale detector is not in progress
mDetector.onTouchEvent(event);
super.onTouchEvent(event);
return true;
}
@Override
public boolean onDown(MotionEvent event) {
Log.d(DEBUG_TAG,"onDown: " );
if(scaling==0)
dv.animateDrag(event.getX(),event.getY());
return true;
}
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
Log.d(DEBUG_TAG, "onFling: " );
return true;
}
@Override
public void onLongPress(MotionEvent event) {
Log.d(DEBUG_TAG, "onLongPress: ");
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
if(scaling>0) return false;
dv.tryDrag(e2.getX(),e2.getY());
return true;
}
@Override
public void onShowPress(MotionEvent event) {
Log.d(DEBUG_TAG, "onShowPress: ");
}
@Override
public boolean onSingleTapUp(MotionEvent event) {
Log.d(DEBUG_TAG, "onSingleTapUp: " );
return true;
}
@Override
public boolean onDoubleTap(MotionEvent event) {
Log.d(DEBUG_TAG, "onDoubleTap: ");
return true;
}
@Override
public boolean onDoubleTapEvent(MotionEvent event) {
Log.d(DEBUG_TAG, "onDoubleTapEvent: ");
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
Log.d(DEBUG_TAG, "onSingleTapConfirmed: ");
int pointerIndex0 = event.findPointerIndex(event.getPointerId(0));
// Get the 1st pointer's current position
float x0 = event.getX(pointerIndex0);
float y0 = event.getY(pointerIndex0);
Log.d(TAG, "X0= "+x0+ " Y0=" + y0);
if(RactangleCount<5){
dv.setCoordinates(x0, y0);
if (safeToTakePicture && prvw) {
((FrameLayout) findViewById(R.id.preview)).addView(dv);
safeToTakePicture = false;
preview.camera.takePicture(shutterCallback, rawCallback, jpegCallback);
prvw=false;
}
RactangleCount++;
}
return true;
}
@Override
public boolean onDrag(View v, DragEvent event) {
// TODO Auto-generated method stub
Log.d(TAG,"on Drag");
// dv.animateDrag(event.getX(),event.getY());
//dv.tryDrag(e2.getX(),e2.getY());
return false;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
scaling++;
Log.d(TAG,"on scale");
scaleFactorX= detector.getCurrentSpanX()/detector.getPreviousSpanX();
scaleFactorY= detector.getCurrentSpanY()/detector.getPreviousSpanY();
Log.d(TAG,"on" + "Xfactor"+scaleFactorX+"Yfactor"+scaleFactorY);
dv.doScale(scaleFactorX,scaleFactorY);
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
// TODO Auto-generated method stub
scaling=1;
Log.d(TAG,"on scale begin");
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
// TODO Auto-generated method stub
Log.d(TAG,"on scale end");
scaling=0;
}
}
solved..! if anyone has a same kind of a problem, the answer is check the rectangle boundaries. The top y coordinates always should be smaller than bottom y coordinates. Otherwise the surface view may give unexpected results.
this is the line with an error.
tempRect.set(tempRect.centerX()-tempWidth,tempRect.centerY()+tempHeight,tempRect.centerX()+tempWidth,tempRect.centerY()-tempHeight);
it should be corrected as
tempRect.set(tempRect.centerX()-tempWidth,tempRect.centerY()-tempHeight,tempRect.centerX()+tempWidth,tempRect.centerY()+tempHeight);