Trying to Zoom ImageView
<p>I am trying to zoom the ImageView below is the xml , code and error report .... It works properly ..it also gets zoom in and zoom out but after two or three times it gets crash ...It gives error at the spacing function event.get(X)... saying Pointer index out of range...</p>

<p>here is the xml </p>

<pre><code>    &lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;FrameLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent" &gt;
   &lt;ImageView android:id="@+id/imageView"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
         android:src="@drawable/gm01"
         android:scaleType="matrix" &gt;
   &lt;/ImageView&gt;
&lt;/FrameLayout&gt;
</code></pre>

<p>Here is the activity </p>

<pre><code>    package com.imageviewzoomactivity;

import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class ImageViewZoomActivityActivity extends Activity implements OnTouchListener {
   private static final String TAG = "Touch";
   // These matrices will be used to move and zoom image
   Matrix matrix = new Matrix();
   Matrix savedMatrix = new Matrix();
   Matrix savedMatrix2 = new Matrix();

   private static final int WIDTH = 0;
    private static final int HEIGHT = 1;
   // We can be in one of these 3 states
   static final int NONE = 0;
   static final int DRAG = 1;
   static final int ZOOM = 2;
   int mode = NONE;

   // Remember some things for zooming
   PointF start = new PointF();
   PointF mid = new PointF();
   float oldDist = 1f;

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      ImageView view = (ImageView) findViewById(R.id.imageView);
      view.setOnTouchListener(this);
   }

   @Override
   public boolean onTouch(View v, MotionEvent event) {
      ImageView view = (ImageView) v;
      int rotation = 25;
      // Dump touch event to log
      dumpEvent(event);

      // Handle touch events here...
      switch (event.getAction() &amp; MotionEvent.ACTION_MASK) {
      /*case MotionEvent.ACTION_DOWN:
         savedMatrix.set(matrix);
         start.set(event.getX(), event.getY());
         Log.d(TAG, "mode=DRAG");
         mode = DRAG;
         break;*/



      case MotionEvent.ACTION_POINTER_DOWN:
         oldDist = spacing(event);
         Log.d(TAG, "oldDist=" + oldDist);
         if (oldDist &gt; 10f) {
            savedMatrix.set(matrix);
            midPoint(mid, event);
            mode = ZOOM;
            Log.d(TAG, "mode=ZOOM");
         }
         break;

    case MotionEvent.ACTION_UP:

         mode = NONE;
         Log.d(TAG, "mode=NONE");
         savedMatrix.set(matrix);
        // matrix.postRotate(90);
         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);
            Log.d(TAG, "newDist=" + newDist);
            if (newDist &gt; 10f) {
               matrix.set(savedMatrix);
               float scale = newDist / oldDist;
               matrix.postScale(scale, scale, mid.x, mid.y);
            }
         }
         break;
      }

      fixing(v);
      view.setImageMatrix(savedMatrix2);
      return true; // indicate event was handled
   }



/** Show an event in the LogCat view, for debugging */
   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());
   }

   /** Determine the space between the first two fingers */
   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);
   }

   /** Calculate the mid point of the first two fingers */
   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);
   }


   public void fixing(View v)
   {

   float[] value = new float[9];
           matrix.getValues(value);

   float[] savedValue = new float[9];
           savedMatrix2.getValues(savedValue);

           int width = v.getWidth();
           int height = v.getHeight();

           Drawable d = getResources().getDrawable(v.getId());
           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] &gt; width-1)   
               value[2] = width-10;
           else if (value[5] &gt; height - 1)   
               value[5] = height - 10;
           else if (value[2] &lt; -(scaleWidth-1))  
               value[2] = -(scaleWidth-10);
           else if (value[5] &lt; -(scaleHeight-1))   
               value[5] = -(scaleHeight-10);

           float MAX_ZOOM=2;
           // maximum zoom ratio: MAx
           if (value[0] &gt; MAX_ZOOM || value[4] &gt; MAX_ZOOM){
               value[0] = MAX_ZOOM;
               value[4] = MAX_ZOOM;
               //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);
   }        
}
</code></pre>

<p>Almost completed but it gets crashed after some time .... at the point of spacing its hows out of index event.getX(0) ??? here is the Logcat Report</p>

<pre><code>03-06 16:33:17.960: E/AndroidRuntime(6534): FATAL EXCEPTION: main
03-06 16:33:17.960: E/AndroidRuntime(6534): java.lang.IllegalArgumentException: pointerIndex out of range
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.MotionEvent.nativeGetAxisValue(Native Method)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.MotionEvent.getX(MotionEvent.java:1549)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at com.imageviewzoomactivity.ImageViewZoomActivityActivity.spacing(ImageViewZoomActivityActivity.java:136)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at com.imageviewzoomactivity.ImageViewZoomActivityActivity.onTouch(ImageViewZoomActivityActivity.java:89)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.View.dispatchTouchEvent(View.java:4622)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1333)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1333)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1333)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1333)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1862)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1286)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.app.Activity.dispatchTouchEvent(Activity.java:2315)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1835)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.View.dispatchPointerEvent(View.java:4694)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2419)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.view.ViewRoot.handleMessage(ViewRoot.java:2080)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.os.Handler.dispatchMessage(Handler.java:99)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.os.Looper.loop(Looper.java:132)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at android.app.ActivityThread.main(ActivityThread.java:4126)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at java.lang.reflect.Method.invokeNative(Native Method)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at java.lang.reflect.Method.invoke(Method.java:491)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
03-06 16:33:17.960: E/AndroidRuntime(6534):     at dalvik.system.NativeStart.main(Native Method)
</code></pre>
