How to detect single finger touch and two finger touch in android?
<p>I am creating an android app where I am zooming an <code>ImageView</code> [pinch zoom(with image translation)] and also I have to rotate the <code>ImageView</code> with two finger movement only. Because I want to translate the <em>Image</em> [scroll] through single finger movement. When I didn't added rotation code pinch zoom and translation worked perfectly but after adding rotation coded image rotates on single finger movement and doesn't translate. I want to have a check that whenever user is moving two fingers on <code>ImageView</code> then <em>Image</em> should rotate otherwise not so that <em>Image</em> translation will not be disturbed. How it can be achieved?
Here is my code. Any help will be appreciated</p>

<pre><code>public class CustomizedImageView extends ImageView {
Matrix matrix;
// 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 last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 3f;
float[] m;
int viewWidth, viewHeight;

static final int CLICK = 3;

float saveScale = 1f;

protected float origWidth, origHeight;

int oldMeasuredWidth, oldMeasuredHeight;

ScaleGestureDetector mScaleDetector;

Context context;
float viewRotation;
double fingerRotation;
double newFingerRotation;

public CustomizedImageView(Context context) {
    super(context);
    sharedConstructing(context);
}

public CustomizedImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    sharedConstructing(context);
}

private void sharedConstructing(Context context) {

    super.setClickable(true);

    this.context = context;

    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());

    matrix = new Matrix();

    m = new float[9];

    setImageMatrix(matrix);

    setScaleType(ScaleType.MATRIX);

    setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {

            mScaleDetector.onTouchEvent(event);

            PointF curr = new PointF(event.getX(), event.getY());
            final float x = event.getX();
            final float y = event.getY();
            final float new_x = getWidth() / 2;
            final float new_y = getHeight() / 2;

            switch (event.getAction()) {

                case MotionEvent.ACTION_DOWN:
                    //Follwing Statements are to TRANSLATE(SCROLL) IMAGE
                    //*************************************************************************
                    last.set(curr);

                    start.set(last);

                    mode = DRAG;
                    //*************************************************************************
                    //Follwing Statements are to ROTATE IMAGE With Finger Movement
                    viewRotation = getRotation();
                    fingerRotation = Math.toDegrees(Math.atan2(x - new_x, new_y - y));
                    //*************************************************************************


                    break;

                case MotionEvent.ACTION_MOVE:
                    //Follwing Statements are to TRANSLATE(SCROLL) IMAGE
                    //*************************************************************************

                    if (mode == DRAG) {

                        float deltaX = curr.x - last.x;

                        float deltaY = curr.y - last.y;

                        float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);

                        float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale);

                        matrix.postTranslate(fixTransX, fixTransY);

                        fixTrans();

                        last.set(curr.x, curr.y);
                        //**********************************************************************
                        //Follwing Statements are to ROTATE IMAGE With Finger Movement
                        newFingerRotation = Math.toDegrees(Math.atan2(x - new_x, new_y - y));
                        setRotation((float) (viewRotation + newFingerRotation - fingerRotation));
                        //*************************************************************************




                    }

                    break;

                case MotionEvent.ACTION_UP:
                    //Follwing Statements are to TRANSLATE(SCROLL) IMAGE
                    //*************************************************************************
                    mode = NONE;

                    int xDiff = (int) Math.abs(curr.x - start.x);

                    int yDiff = (int) Math.abs(curr.y - start.y);

                    if (xDiff &lt; CLICK &amp;&amp; yDiff &lt; CLICK)

                        performClick();
                    //*************************************************************************
                    //Follwing Statements are to ROTATE IMAGE With Finger Movement
                    fingerRotation = newFingerRotation = 0.0f;
                    //*************************************************************************


                    break;

                case MotionEvent.ACTION_POINTER_UP:
                    //Follwing Statements are to TRANSLATE(SCROLL) IMAGE
                    //*************************************************************************
                    mode = NONE;
                    //*************************************************************************

                    break;

            }

            setImageMatrix(matrix);

            invalidate();

            return true; // indicate event was handled

        }

    });
}
public void setMaxZoom(float x) {

    maxScale = x;

}

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {

        mode = ZOOM;

        return true;

    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {

        float mScaleFactor = detector.getScaleFactor();

        float origScale = saveScale;

        saveScale *= mScaleFactor;

        if (saveScale &gt; maxScale) {

            saveScale = maxScale;

            mScaleFactor = maxScale / origScale;

        } else if (saveScale &lt; minScale) {

            saveScale = minScale;

            mScaleFactor = minScale / origScale;

        }

        if (origWidth * saveScale &lt;= viewWidth || origHeight * saveScale &lt;= viewHeight)

            matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);

        else

            matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());

        fixTrans();

        return true;

    }

}

void fixTrans() {

    matrix.getValues(m);

    float transX = m[Matrix.MTRANS_X];

    float transY = m[Matrix.MTRANS_Y];

    float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);

    float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);

    if (fixTransX != 0 || fixTransY != 0)

        matrix.postTranslate(fixTransX, fixTransY);

}


float getFixTrans(float trans, float viewSize, float contentSize) {

    float minTrans, maxTrans;

    if (contentSize &lt;= viewSize) {

        minTrans = 0;

        maxTrans = viewSize - contentSize;

    } else {

        minTrans = viewSize - contentSize;

        maxTrans = 0;

    }

    if (trans &lt; minTrans)

        return -trans + minTrans;

    if (trans &gt; maxTrans)

        return -trans + maxTrans;

    return 0;

}

float getFixDragTrans(float delta, float viewSize, float contentSize) {

    if (contentSize &lt;= viewSize) {

        return 0;

    }

    return delta;

}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    viewWidth = MeasureSpec.getSize(widthMeasureSpec);

    viewHeight = MeasureSpec.getSize(heightMeasureSpec);

    //
    // Rescales image on rotation
    //
    if (oldMeasuredHeight == viewWidth &amp;&amp; oldMeasuredHeight == viewHeight

            || viewWidth == 0 || viewHeight == 0)

        return;

    oldMeasuredHeight = viewHeight;

    oldMeasuredWidth = viewWidth;

    if (saveScale == 1) {

        //Fit to screen.

        float scale;

        Drawable drawable = getDrawable();

        if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0)

            return;

        int bmWidth = drawable.getIntrinsicWidth();

        int bmHeight = drawable.getIntrinsicHeight();

        Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);

        float scaleX = (float) viewWidth / (float) bmWidth;

        float scaleY = (float) viewHeight / (float) bmHeight;

        scale = Math.min(scaleX, scaleY);

        matrix.setScale(scale, scale);

        // Center the image

        float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight);

        float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth);

        redundantYSpace /= (float) 2;

        redundantXSpace /= (float) 2;

        matrix.postTranslate(redundantXSpace, redundantYSpace);

        origWidth = viewWidth - 2 * redundantXSpace;

        origHeight = viewHeight - 2 * redundantYSpace;

        setImageMatrix(matrix);

    }

    fixTrans();

}
</code></pre>