title: Android - How to get point after pinch to zoom?
body: <blockquote>
    <p><img src="https://i.stack.imgur.com/runiJ.jpg" alt="enter image description here"></p>
  </blockquote>
  
  <p>This image is my question. Could you help me?</p>
  
  <pre><code>    import java.io.IOException;
      import java.net.InetSocketAddress;
      import java.net.Socket;
      import java.net.SocketAddress;
  
      import android.content.Context;
      import android.graphics.Bitmap;
      import android.graphics.Matrix;
      import android.graphics.PointF;
      import android.graphics.drawable.Drawable;
      import android.util.AttributeSet;
      import android.util.FloatMath;
      import android.util.Log;
      import android.view.MotionEvent;
      import android.widget.ImageView;
      import android.widget.Toast;
      import android.widget.ImageView.ScaleType;
  
      public class ImageViewTouch extends ImageView{
  private static final String TAG = "ImageViewTouch";
  private static final boolean D = false;
  
  private Matrix matrix;
  private Matrix savedMatrix;
  private Matrix savedMatrix2;
  
  private Drawable d;
  
  private static final int NONE = 0;
  private static final int DRAG = 1;
  private static final int ZOOM = 2;
  private int mode = NONE;
  
  private PointF start = new PointF();
  private PointF mid = new PointF();
  private float oldDist = 1f;
  
  private static final int WIDTH = 0;
  private static final int HEIGHT = 1;
  
  private boolean isInit = true;
  
  private boolean isMoving;
  private boolean isScaling;
  private boolean isRestoring;
  
  public ImageViewTouch(Context context, AttributeSet attrs, int defStyle) 
  {
      super(context, attrs, defStyle);
      setScaleType(ScaleType.MATRIX);
      matrix = new Matrix();
      savedMatrix = new Matrix();
      savedMatrix2 = new Matrix();
  }
  
  public ImageViewTouch(Context context, AttributeSet attrs) {
      this(context, attrs, 0);
  }
  
  public ImageViewTouch(Context context) {
      this(context, null);
  
  }
  
  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) 
  {
      if (D) Log.i(TAG, "onLayout");
      d = this.getDrawable();
      super.onLayout(changed, left, top, right, bottom);
      if (isInit == false)
      {
          init();
          isInit = true;
      }
  }
  
  @Override
  public void setImageBitmap(Bitmap bm) 
  {
      if (D) Log.i(TAG, "setImageBitmap");
      super.setImageBitmap(bm);
      if(isInit == true)
      {
          init();
      }
  }
  
  @Override
  public void setImageResource(int resId) {
      if (D) Log.i(TAG, "setImageResource");
      super.setImageResource(resId);
      d = getDrawable();
      isInit = false;
      init();
  }
  
  protected void init() 
  {
      d = this.getDrawable();
      initImgPos();
      setImageMatrix(matrix);
      isInit = false;
  }
  
  public void initImgPos()
  {
      float[] value = new float[9];
      this.matrix.getValues(value);
  
      int width = this.getWidth();
      int height = this.getHeight();
  
      if (d == null)  return;
      int imageWidth = d.getIntrinsicWidth();
      int imageHeight = d.getIntrinsicHeight();
      int scaleWidth = (int) (imageWidth * value[0]);
      int scaleHeight = (int) (imageHeight * value[4]);
  
      if (imageWidth &gt; width || imageHeight &gt; height)
      {
  
          float xratio = (float)width / (float)imageWidth;
          float yratio = (float)height / (float)imageHeight;
  
          // Math.min fits the image to the shorter axis. (with letterboxes around)
          // Math.max fits the image th the longer axis. (with the other axis cropped)
          value[0] = value[4] = Math.max(xratio, yratio);
      }
  
      scaleWidth = (int) (imageWidth * value[0]);
      scaleHeight = (int) (imageHeight * value[4]);
  
      // align the image to the top left corner
      value[2] = 0;
      value[5] = 0;
  
      // center the image. it will be aligned to the top left corner otherwise.
      value[2] = (float) width / 2 - (float)scaleWidth / 2;
      value[5] = (float) height / 2 - (float)scaleHeight / 2;
  
      matrix.setValues(value);
      setImageMatrix(matrix);
  }
  
  @Override
  public boolean onTouchEvent(MotionEvent event) 
  {
      if(D) dumpEvent(event);
  
      switch (event.getAction() &amp; MotionEvent.ACTION_MASK) 
      {
      case MotionEvent.ACTION_DOWN:
          savedMatrix.set(matrix);
          start.set(event.getX(), event.getY());
          mode = DRAG;
  
          break;
  
      case MotionEvent.ACTION_POINTER_DOWN:
          oldDist = spacing(event);
          if (oldDist &gt; 10f) 
          {
              savedMatrix.set(matrix);
              midPoint(mid, event);
              mode = ZOOM;
          }
          break;
  
      case MotionEvent.ACTION_UP:
  
      case MotionEvent.ACTION_POINTER_UP:
          mode = NONE;
          restore(matrix);
          break;
  
      case MotionEvent.ACTION_MOVE:
          if (mode == DRAG) 
          {
              matrix.set(savedMatrix);
              matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
          }
          else if (mode == ZOOM) 
          {
              float newDist = spacing(event);
              if (newDist &gt; 10f) 
              {
                  matrix.set(savedMatrix);
                  float scale = newDist / oldDist;
                  matrix.postScale(scale, scale, mid.x, mid.y);
              }
          }
          break;
      }
  
      // Matrix value modification
      // comment out below 2 lines to remove all restrictions on image transformation.
      matrixTuning(matrix);
      setImageMatrix(savedMatrix2);
  
      return true;
  }
  
  private float spacing(MotionEvent event) 
  {
      float x = event.getX(0) - event.getX(1);
      float y = event.getY(0) - event.getY(1);
      return FloatMath.sqrt(x * x + y * y);
  }
  
  private void midPoint(PointF point, MotionEvent event) 
  {
      float x = event.getX(0) + event.getX(1);
      float y = event.getY(0) + event.getY(1);
      point.set(x / 2, y / 2);
  }
  
  private void matrixTuning(Matrix matrix)
  {
      float[] value = new float[9];
      matrix.getValues(value);
      float[] savedValue = new float[9];
      savedMatrix2.getValues(savedValue);
  
      int width = getWidth();
      int height = getHeight();
  
  
      Drawable d = getDrawable();
      if (d == null)  return;
      int imageWidth = d.getIntrinsicWidth();
      int imageHeight = d.getIntrinsicHeight();
      int scaleWidth = (int) (imageWidth * value[0]);
      int scaleHeight = (int) (imageHeight * value[4]);
  
      // don't let the image go outside
      if (value[2] &lt; width - scaleWidth)   value[2] = width - scaleWidth;
      if (value[5] &lt; height - scaleHeight)   value[5] = height - scaleHeight;
      if (value[2] &gt; 0)   value[2] = 0;
      if (value[5] &gt; 0)   value[5] = 0;
  
      // maximum zoom ratio: 2x
      if (value[0] &gt; 2 || value[4] &gt; 2)
      {
          value[0] = savedValue[0];
          value[4] = savedValue[4];
          value[2] = savedValue[2];
          value[5] = savedValue[5];
      }
  
      // don't let the image become smaller than the screen
      if (imageWidth &gt; width || imageHeight &gt; height)
      {
          if (scaleWidth &lt; width &amp;&amp; scaleHeight &lt; height)
          {
              int target = WIDTH;
              if (imageWidth &lt; imageHeight) target = HEIGHT;
  
              if (target == WIDTH) value[0] = value[4] = (float)width / imageWidth;
              if (target == HEIGHT) value[0] = value[4] = (float)height / imageHeight;
  
              scaleWidth = (int) (imageWidth * value[0]); 
              scaleHeight = (int) (imageHeight * value[4]);
  
              if (scaleWidth &gt; width) value[0] = value[4] = (float)width / imageWidth;
              if (scaleHeight &gt; height) value[0] = value[4] = (float)height / imageHeight;
          }
      }
  
      // don't allow scale down under its size
      else
      {
          if (value[0] &lt; 1)   value[0] = 1;
          if (value[4] &lt; 1)   value[4] = 1;
      }
  
      // center the image
      scaleWidth = (int) (imageWidth * value[0]);
      scaleHeight = (int) (imageHeight * value[4]);
      if (scaleWidth &lt; width)
      {
          value[2] = (float) width / 2 - (float)scaleWidth / 2;
      }
      if (scaleHeight &lt; height)
      {
          value[5] = (float) height / 2 - (float)scaleHeight / 2;
      }
  
      matrix.setValues(value);
      savedMatrix2.set(matrix);
  }
  
  private void restore(Matrix m) 
  {
      setImageMatrix(matrix);
  }
  
  private void dumpEvent(MotionEvent event) 
  {
      String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" , "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
      StringBuilder sb = new StringBuilder();
      int action = event.getAction();
      int actionCode = action &amp; MotionEvent.ACTION_MASK;
      sb.append("event ACTION_" ).append(names[actionCode]);
  
      if (actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP) 
      {
          sb.append("(pid " ).append(action &gt;&gt; MotionEvent.ACTION_POINTER_ID_SHIFT);
          sb.append(")" );
      }
      sb.append("[" );
      for (int i = 0; i &lt; event.getPointerCount(); i++) 
      {
          sb.append("#" ).append(i);
          sb.append("(pid " ).append(event.getPointerId(i));
          sb.append(")=" ).append((int) event.getX(i));
          sb.append("," ).append((int) event.getY(i));
          if (i + 1 &lt; event.getPointerCount())
              sb.append(";" );
      }
      sb.append("]" );
      Log.d(TAG, sb.toString());
  }
  }
  </code></pre>
  
  <p>Please give me solution of this question. it operaters this code well for pinch to zoom. but, I cant know point after pinch to zoom. I wnat to know image of absolute point.</p>