title: Draw Rectangle Over ImageView for highlight that can be zoom in-out in android
body: <p>I have been refer this example from SO below are they.</p>
  
  <p>1.<a href="https://stackoverflow.com/questions/8831642/how-to-draw-lines-over-imageview-on-android">Draw Line Over ImageView</a></p>
  
  <p>2.<a href="https://stackoverflow.com/questions/6956774/android-draw-picture-over-imageview">Draw Picture Over ImageView</a></p>
  
  <p>3.I have use this ImageView Class for my image to become zoom in-out <a href="http://code.google.com/p/scale-imageview-android/source/browse/src/com/matabii/dev/scaleimageview/ScaleImageView.java" rel="nofollow noreferrer">Image Pinch zoom code google</a>.</p>
  
  <p><strong>Now what i am try to do is :</strong></p>
  
  <p>I want to  make zoom in by pinching the screen and other point is that when i do single tap a rectangle should be drawn over image view and i also want this rectangle should get zoom in &amp; out with imageView's Zoom in and Zoom Out and i want to use it through <code>ScaleImageView</code>  class.</p>
  
  <p>Output of this should look like below image.</p>
  
  <p><img src="https://i.stack.imgur.com/5KBVj.png" alt="you can see when i make single tap over ImageViewit will draw rectangle like showing in image "></p>
  
  <p>And i also known that ,this can be done by Using <code>Relative Layout</code> or may be by using <code>SurfaceView</code>in android but i am new for use Surface view and i also worry about if i use Another View over imageView to draw then do this both view work for zoom in and out . If i use SurfaceView over ImageView then do Image Can be able to zoom in and out .</p>
  
  <p>By using this pinch zoom in-out example from here.<a href="http://code.google.com/p/scale-imageview-android/" rel="nofollow noreferrer">example that i use pinch zoom</a>.</p>
  
  <p>Now i draw Rectangle on Single Touch by below code in that example.</p>
  
  <pre><code>@Override
      protected void onDraw(Canvas canvas) {
          super.onDraw(canvas);
          Log.v("Log_tag", "Draw Image View");
          //Bitmap _scratch = BitmapFactory.decodeResource(getResources(), R.drawable.rect_image);
          //canvas.drawColor(Color.BLACK);
          //canvas.drawBitmap(_scratch, 10, 10, null);
          Drawable d = getDrawable();
          //Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
          Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.RGB_565);
          /*if(bitmap!=null){
              if (x1 &gt; 0 || x2 &gt; 0 || y1 &gt; 0 || y2 &gt; 0){
                    Log.v("Log_tag", "ImageBitmap is draw");
                  //Canvas mCanvas=new Canvas(bitmap);
                  //mCanvas.drawRect(x1, y1, x2, y2, mPaint);
                  //  canvas.clipRect(left, top, right, bottom);
                     paint.setStyle(Paint.Style.FILL_AND_STROKE);
                      paint.setStrokeWidth(1);
                     paint.setColor(0xFF000000
                        + ((int)(PRESET_PRESSURE * pressure) &lt;&lt;16)
                        + ((int)(PRESET_PRESSURE * pressure) &lt;&lt; 8)
                        + (int)(PRESET_PRESSURE * pressure));
                     //mCanvas.drawCircle(x1, y1, (PRESET_SIZE * size), paint);
              }
  
          }*/
          //canvas.save();
          //canvas.translate(mPosX, mPosY);
         // canvas.scale(mScaleFactor, mScaleFactor);
          mBitmapDrawable.draw(canvas);
          Paint myPaint = new Paint();
          myPaint.setColor(Color.GREEN);
          myPaint.setStyle(Paint.Style.STROKE);
          myPaint.setStrokeWidth(1);
          Log.v("Log_tag", "Redraw with this point");
          canvas.drawRect(rect_x1-30,rect_y1-30, rect_x1+30, rect_y1+30, myPaint);
          mCanvasMatrix=canvas.getMatrix();
          mImageCanvas=canvas;
  
          canvas.setMatrix(mCanvasMatrix);
          //canvas.restore();
  
      }
  </code></pre>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Below is my class used for ImageView pinch zoom.</p>
  
  <pre><code>public class ImageViewScale extends ImageView implements OnTouchListener {
      @Override
      protected void onDraw(Canvas canvas) {
          super.onDraw(canvas);
          //canvas.save();
          //canvas.scale(mScale, mScale);
          mCanvasMatrix=canvas.getMatrix();
          Paint myPaint = new Paint();
          myPaint.setColor(Color.GREEN);
          myPaint.setStyle(Paint.Style.STROKE);
          myPaint.setStrokeWidth(1);
          if(mCanvasMatrix!=null){
              if(orignalRect!=null)
                  mCanvasMatrix.mapRect(orignalRect);
          }
          if(orignalRect!=null){
              canvas.drawRect(orignalRect,myPaint);
          }
          //canvas.drawRect(rect_x1-30,rect_y1-30, rect_x1+30, rect_y1+30, myPaint);
          int canavs_width=canvas.getWidth();
          int canavs_height=canvas.getHeight();
          canvas.setMatrix(mCanvasMatrix);
          //canvas.setMatrix(mMatrix);
          if(mDrawable!=null){
              //mDrawable.draw(canvas);
              Log.v("Log_tag", "draw with Canvas is done  W:"+ canavs_width+"H:"+ canavs_height);
          }
          //canvas.restore();
      }
  
      private float MAX_SCALE = 2f;
      private int DOUBLE_TAP_SECOND = 400;
  
      private float CANVAS_MAX_SCALE=2f;
  
      float rect_x1=50;
      float rect_y1=150;
  
      private Matrix mMatrix;
      private Matrix mCanvasMatrix;
  
      private final float[] mCanvasMatrixValues=new float[9];
      private final float[] mMatrixValues = new float[9];
      RectF orignalRect;
      private Drawable mDrawable;
      private ImageView mImageView;
      // display width height.
      private int mWidth;
      private int mHeight;
  
      private int mIntrinsicWidth;
      private int mIntrinsicHeight;
  
      private int mCanvasWidth;
      private int mCanvasHeight;
  
  
      private float mScale;
      private float mMinScale;
  
      private float mCanvasMinScale;
  
      // double tap for determining
      private long mLastTime = 0;
      private boolean isDoubleTap;
      private int mDoubleTapX;
      private int mDoubleTapY;
  
      private float mPrevDistance;
      private boolean isScaling;
  
      private int mPrevMoveX;
      private int mPrevMoveY;
  
      String TAG = "ScaleImageView";
  
      public ImageViewScale(Context context, AttributeSet attr) {
          super(context, attr);
          initialize();
      }
  
      public ImageViewScale(Context context) {
          super(context);
          initialize();
      }
  
      @Override
      public void setImageBitmap(Bitmap bm) {
          super.setImageBitmap(bm);
          this.initialize();
  
      }
  
      private void initialize() {
          this.setScaleType(ScaleType.MATRIX);
          this.mMatrix = new Matrix();
          Drawable d = getDrawable();
          mDrawable=d;
          if (d != null) {
              mIntrinsicWidth = d.getIntrinsicWidth();
              mIntrinsicHeight = d.getIntrinsicHeight();
              setOnTouchListener(this);
          }
      }
  
      @Override
      protected boolean setFrame(int l, int t, int r, int b) {
          Log.v("Log_tag", "Size are here "+ l + t + r+ b);
          mWidth = r - l;
          mHeight = b - t;
  
          mMatrix.reset();
          mScale = (float) r / (float) mIntrinsicWidth;
          int paddingHeight = 0;
          int paddingWidth = 0;
          // scaling vertical
          if (mScale * mIntrinsicHeight &gt; mHeight) {
              mScale = (float) mHeight / (float) mIntrinsicHeight;
              mMatrix.postScale(mScale, mScale);
              paddingWidth = (r - mWidth) / 2;
              paddingHeight = 0;
              // scaling horizontal
          } else {
              mMatrix.postScale(mScale, mScale);
              paddingHeight = (b - mHeight) / 2;
              paddingWidth = 0;
          }
          mMatrix.postTranslate(paddingWidth, paddingHeight);
  
          setImageMatrix(mMatrix);
          mMinScale = mScale;
          zoomTo(mScale, mWidth / 2, mHeight / 2);
          cutting();
          return super.setFrame(l, t, r, b);
      }
  
      protected float getValue(Matrix matrix, int whichValue) {
          matrix.getValues(mMatrixValues);
          return mMatrixValues[whichValue];
      }
      //New Added
      protected float getCanvasValue(Matrix matrix,int whichvalues){
          mCanvasMatrix.getValues(mCanvasMatrixValues);
          return mCanvasMatrixValues[whichvalues];
      }
  
      protected float getScale() {
          return getValue(mMatrix, Matrix.MSCALE_X);
      }
  
      //New added  Method
      protected float getCanvasScale(){
          return getCanvasValue(mCanvasMatrix, Matrix.MSCALE_X);
      }
  
      protected float getTranslateX() {
          return getValue(mMatrix, Matrix.MTRANS_X);
      }
  
      //New added Method
      protected float getCanvasTranslateX(){
          return getCanvasValue(mCanvasMatrix, Matrix.MTRANS_X);
      }
  
  
      protected float getTranslateY() {
          return getValue(mMatrix, Matrix.MTRANS_Y);
      }
  
      //New Added Method
      protected float getCanvasTranslateY(){
          return getCanvasValue(mCanvasMatrix, Matrix.MTRANS_Y);
      }
  
      protected void maxZoomTo(int x, int y) {
          if (mMinScale != getScale() &amp;&amp; (getScale() - mMinScale) &gt; 0.1f) {
              // threshold 0.1f
              float scale = mMinScale / getScale();
              zoomTo(scale, x, y);
          } else {
              float scale = MAX_SCALE / getScale();
              zoomTo(scale, x, y);
          }
      }
  
  
  
  
      protected void zoomTo(float scale, int x, int y) {
          if (getScale() * scale &lt; mMinScale) {
              return;
          }
          if (scale &gt;= 1 &amp;&amp; getScale() * scale &gt; MAX_SCALE) {
              return;
          }
          mMatrix.postScale(scale, scale);
          // move to center
          mMatrix.postTranslate(-(mWidth * scale - mWidth) / 2,
                  -(mHeight * scale - mHeight) / 2);
  
          // move x and y distance
          mMatrix.postTranslate(-(x - (mWidth / 2)) * scale, 0);
          mMatrix.postTranslate(0, -(y - (mHeight / 2)) * scale);
          setImageMatrix(mMatrix);
      }
  
  
      protected void zoomToCanvas(float scale,int x,int y){
          if(getCanvasScale()* scale&lt;mCanvasMinScale){
              return;
          }
  
          if(scale&gt;=1 &amp;&amp; getCanvasScale()*scale&gt; CANVAS_MAX_SCALE){
              return;
          }
          mCanvasMatrix.postScale(scale, scale);
  
  
  
      }
  
      public void cutting() {
          int width = (int) (mIntrinsicWidth * getScale());
          int height = (int) (mIntrinsicHeight * getScale());
          if (getTranslateX() &lt; -(width - mWidth)) {
              mMatrix.postTranslate(-(getTranslateX() + width - mWidth), 0);
          }
          if (getTranslateX() &gt; 0) {
              mMatrix.postTranslate(-getTranslateX(), 0);
          }
          if (getTranslateY() &lt; -(height - mHeight)) {
              mMatrix.postTranslate(0, -(getTranslateY() + height - mHeight));
          }
          if (getTranslateY() &gt; 0) {
              mMatrix.postTranslate(0, -getTranslateY());
          }
          if (width &lt; mWidth) {
              mMatrix.postTranslate((mWidth - width) / 2, 0);
          }
          if (height &lt; mHeight) {
              mMatrix.postTranslate(0, (mHeight - height) / 2);
          }
          setImageMatrix(mMatrix);
      }
  
      private float distance(float x0, float x1, float y0, float y1) {
          float x = x0 - x1;
          float y = y0 - y1;
          return FloatMath.sqrt(x * x + y * y);
      }
  
      private float dispDistance() {
          return FloatMath.sqrt(mWidth * mWidth + mHeight * mHeight);
      }
  
      @Override
      public boolean onTouchEvent(MotionEvent event) {
          int touchCount = event.getPointerCount();
          switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
          case MotionEvent.ACTION_POINTER_1_DOWN:
          case MotionEvent.ACTION_POINTER_2_DOWN:
              if (touchCount &gt;= 2) {
                  float distance = distance(event.getX(0), event.getX(1),
                          event.getY(0), event.getY(1));
                  mPrevDistance = distance;
                  isScaling = true;
              } else {
                  if (System.currentTimeMillis() &lt;= mLastTime + DOUBLE_TAP_SECOND) {
                      if (30 &gt; Math.abs(mPrevMoveX - event.getX())
                              + Math.abs(mPrevMoveY - event.getY())) {
                          isDoubleTap = true;
                          mDoubleTapX = (int) event.getX();
                          mDoubleTapY = (int) event.getY();
                      }
                  }
                  mLastTime = System.currentTimeMillis();
                  mPrevMoveX = (int) event.getX();
                  mPrevMoveY = (int) event.getY();
              }
              break;
          case MotionEvent.ACTION_MOVE:
              if (touchCount &gt;= 2 &amp;&amp; isScaling) {
                  float dist = distance(event.getX(0), event.getX(1),
                          event.getY(0), event.getY(1));
                  float scale = (dist - mPrevDistance) / dispDistance();
                  mPrevDistance = dist;
                  scale += 1;
                  scale = scale * scale;
                  zoomTo(scale, mWidth / 2, mHeight / 2);
                  cutting();
              } else if (!isScaling) {
                  int distanceX = mPrevMoveX - (int) event.getX();
                  int distanceY = mPrevMoveY - (int) event.getY();
                  mPrevMoveX = (int) event.getX();
                  mPrevMoveY = (int) event.getY();
                  mMatrix.postTranslate(-distanceX, -distanceY);
                  cutting();
              }
              break;
          case MotionEvent.ACTION_UP:
          case MotionEvent.ACTION_POINTER_UP:
          case MotionEvent.ACTION_POINTER_2_UP:
              if (event.getPointerCount() &lt;= 1) {
                  isScaling = false;
                  if (isDoubleTap) {
                      if (30 &gt; Math.abs(mDoubleTapX - event.getX())
                              + Math.abs(mDoubleTapY - event.getY())) {
                          maxZoomTo(mDoubleTapX, mDoubleTapY);
                          cutting();
                      }
                  }
              }
              isDoubleTap = false;
              break;
          }
          return true;
      }
  
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          int count_touch=event.getPointerCount();
          switch(event.getAction()){
          case MotionEvent.ACTION_UP:
              float point_x=event.getX();
              float point_y=event.getY();
              rect_x1=point_x;
              rect_y1=point_y;
              if(count_touch==1){
                  orignalRect=new RectF(rect_x1-30, rect_y1-30, rect_x1+30,  rect_y1+30);
                  invalidate();
              }
              break;
          }
  
          return super.onTouchEvent(event);
      }
  }
  </code></pre>