Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect single finger touch and two finger touch in android?

I am creating an android app where I am zooming an ImageView [pinch zoom(with image translation)] and also I have to rotate the ImageView with two finger movement only. Because I want to translate the Image [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 ImageView then Image should rotate otherwise not so that Image translation will not be disturbed. How it can be achieved? Here is my code. Any help will be appreciated

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 < CLICK && yDiff < 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 > maxScale) {

            saveScale = maxScale;

            mScaleFactor = maxScale / origScale;

        } else if (saveScale < minScale) {

            saveScale = minScale;

            mScaleFactor = minScale / origScale;

        }

        if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= 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 <= viewSize) {

        minTrans = 0;

        maxTrans = viewSize - contentSize;

    } else {

        minTrans = viewSize - contentSize;

        maxTrans = 0;

    }

    if (trans < minTrans)

        return -trans + minTrans;

    if (trans > maxTrans)

        return -trans + maxTrans;

    return 0;

}

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

    if (contentSize <= 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 && 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();

}
like image 583
User Avatar asked Oct 19 '16 05:10

User


2 Answers

The MotionEvent parameter has the number of "pointers" (i.e fingers) for each event.

So MotionEvent.getPointerCount() is your friend.

https://developer.android.com/reference/android/view/MotionEvent.html#getPointerCount

like image 148
Mike Dinescu Avatar answered Sep 30 '22 15:09

Mike Dinescu


You can use MotionEvent.getPointerCount().

like image 22
2hamed Avatar answered Sep 30 '22 15:09

2hamed