title: Android pinch zoom imageview inside gallery
body: <p>I'm creating lazy loaded photo gallery (like facebook)</p>
  
  <p>i'm using cusotme gallery overriding Fling to the make single image paging
  and using custume image view to make the pinch zoom</p>
  
  <p>the result is that the image is working fine (zoom,move etc..) but i can't switch images</p>
  
  <p>my code
  SlowGallery:</p>
  
  <p>public class SlowGallery extends Gallery {</p>
  
  <pre><code>public SlowGallery(Context context) {
      super(context);
  
  }
  
  public SlowGallery(Context context, AttributeSet attrs) {
      super(context, attrs);
  
  }
  
  public SlowGallery(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
  
  }
  
  private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2){
      return e2.getX() &gt; e1.getX();
  }
  
  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){
      Log.d("SlowGallery::onFling","onFinlg");
      int kEvent;
      if(isScrollingLeft(e1, e2)){ //Check if scrolling left
          kEvent = KeyEvent.KEYCODE_DPAD_LEFT;
      }
      else{ //Otherwise scrolling right
          kEvent = KeyEvent.KEYCODE_DPAD_RIGHT;
      }
      onKeyDown(kEvent, null);
      return true;  
  }
  </code></pre>
  
  <p>}</p>
  
  <p>ScaleImageView</p>
  
  <pre><code>public class ScaleImageView extends ImageView implements OnTouchListener {
      private float MAX_SCALE = 2f;
      private int DOUBLE_TAP_SECOND = 400;
  
      private Matrix mMatrix;
      private final float[] mMatrixValues = new float[9];
  
      // display width height.
      private int mWidth;
      private int mHeight;
  
      private int mIntrinsicWidth;
      private int mIntrinsicHeight;
  
      private float mScale;
      private float mMinScale;
  
      // 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 ScaleImageView(Context context, AttributeSet attr) {
              super(context, attr);
              initialize();
      }
  
      public ScaleImageView(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();
              if (d != null) {
                      mIntrinsicWidth = d.getIntrinsicWidth();
                      mIntrinsicHeight = d.getIntrinsicHeight();
                      setOnTouchListener(this);
              }
      }
  
      @Override
      protected boolean setFrame(int l, int t, int r, int 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];
      }
  
      protected float getScale() {
              return getValue(mMatrix, Matrix.MSCALE_X);
      }
  
      protected float getTranslateX() {
              return getValue(mMatrix, Matrix.MTRANS_X);
      }
  
      protected float getTranslateY() {
              return getValue(mMatrix, 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);
      }
  
      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;
      }
  
  
      public boolean onTouch(View v, MotionEvent event) {
              return super.onTouchEvent(event);
      }
  </code></pre>
  
  <p>}</p>
  
  <p>what am i missing ? thanks</p>