Search code examples
androidsurfaceview

Android: How to draw a rectangle on a movable image such that the drawn rectangle also moves along with the image?


I have an image which is movable throughout the screen. Now, I want to draw a rectangle on this image such that when I move the image the rectangle drawn on the image also moves. Currently I am able to draw the rectangle not on the image but on the SurfaceView which contains the image. My current code is below.

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);       


      int w=getWindowManager().getDefaultDisplay().getWidth()-25;
      int h=getWindowManager().getDefaultDisplay().getHeight()-25;

      MySurfaceView mySurface=new MySurfaceView(this,w,h);
      setContentView(mySurface);
  }
}

And I have a class called MySurfaceView.java

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    private Bitmap bitmap ;
    private MyThread thread;
    private int x=20,y=20;int width,height;

    public MySurfaceView(Context context,int w,int h) {
        super(context);

        width=w;
        height=h;
        thread=new MyThread(getHolder(),this);
        getHolder().addCallback(this);
        setFocusable(true);
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        bitmap =BitmapFactory.decodeResource(getResources(), R.drawable.my_pic);
        canvas.drawColor(Color.BLUE);//To make background 
        canvas.drawBitmap(bitmap,x-(bitmap.getWidth()/2),y-(bitmap.getHeight()/2),null);


        Paint paintShape = new Paint();
        paintShape.setColor(Color.BLACK);
        paintShape.setStyle(Paint.Style.STROKE);

        Rect myRectangle = new Rect();
        myRectangle.set(0, 100, canvas.getWidth()/4, canvas.getHeight()/4);

        canvas.drawRect(myRectangle, paintShape);


    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        x=(int)event.getX();
        y=(int)event.getY();

        if(x<25)
                x=25;
         if(x> width)   
                x=width;
         if(y <25)
                y=25;
         if(y > 405)
                y=405;      
        return true;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        thread.startrun(true);
        thread.start();

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {


        thread.startrun(false);
        thread.stop();

    }

    public class MyThread extends Thread{

        private SurfaceHolder msurfaceHolder;
        private MySurfaceView mSurfaceView;
        private boolean mrun =false;

        public MyThread(SurfaceHolder holder, MySurfaceView mSurfaceView) {

            this.msurfaceHolder = holder;
            this.mSurfaceView=mSurfaceView;
        }

        public void startrun(boolean run) {

            mrun=run;
        }

        @SuppressLint("WrongCall")
        @Override
        public void run() {

            super.run();
             Canvas canvas;
             while (mrun) {
                canvas=null;
                 try {
                     canvas = msurfaceHolder.lockCanvas(null);
                      synchronized (msurfaceHolder) {
                       mSurfaceView.onDraw(canvas);
                     }
                 } finally {
                         if (canvas != null) {
                         msurfaceHolder.unlockCanvasAndPost(canvas);
                     }
                 }
             }
          }
    }
 }

Can some one help me out improving my code to accommodate the above desired task. thanks!


Solution

  • Well I figured my own way. It was just a small change in the above code which was necessary. It is enough to define the co-ordinates of rectangle with respect to x and y obtained due to touch events. for example, you can do the following:

    myRectangle.set(x-50, y-50, x+50, y+50);
    

    And the rest will be taken care automatically.