Audum
Audum

Reputation: 219

Scale limits on pinch zoom of android

How to set Max and Min zoom levels for Pinch-Zoom?


Here is my code: //

public class TouchImageView extends ImageView {

     private static final String TAG = "Touch";

        // These matrices will be used to move and zoom image
        Matrix matrix = new Matrix();
        Matrix savedMatrix = new Matrix();
        static PinchZoomExample sPinchZoomExample = null;
        // 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;
        static Bitmap sCurrentImage;

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

        Context context;


        public TouchImageView(Context context) {
            super(context);
            super.setClickable(true);
            this.context = context;

            matrix.setTranslate(1f, 1f);
            setImageMatrix(matrix);
            setScaleType(ScaleType.MATRIX);

            setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent rawEvent) {
                    WrapMotionEvent event = WrapMotionEvent.wrap(rawEvent);

                    // Dump touch event to log
                   /* if (Viewer.isDebug == true){
                        dumpEvent(event);
                    }*/

                    // Handle touch events here...
                    switch (event.getAction() & 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 > 10f) {
                            savedMatrix.set(matrix);
                            midPoint(mid, event);
                            mode = ZOOM;
                            Log.d(TAG, "mode=ZOOM");
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        int xDiff = (int) Math.abs(event.getX() - start.x);
                        int yDiff = (int) Math.abs(event.getY() - start.y);
                        if (xDiff < 8 && yDiff < 8){
                            performClick();
                            sPinchZoomExample.displayGallery();
                        }
                    case MotionEvent.ACTION_POINTER_UP:
                        mode = NONE;
                        Log.d(TAG, "mode=NONE");
                        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 > 10f) {
                                matrix.set(savedMatrix);
                                float scale = newDist / oldDist;

                                matrix.postScale(scale, scale, mid.x, mid.y);

                                //Canvas canvas = new Canvas();

//                              Bitmap bm = Bitmap.createBitmap(sCurrentImage,0, 0, sCurrentImage.getWidth()
//                                      , sCurrentImage.getHeight(), matrix, true);
                                Log.d("SCALE", "scale=" + scale + "  " + getWidth() + "  " + getHeight());
                                //bm.recycle();
                            }
                        }
                        break;
                    }

                    setImageMatrix(matrix);
                    return true; // indicate event was handled
                }

            });
        }


        public void setImage(Bitmap bm, int displayWidth, int displayHeight , PinchZoomExample pze) { 
            super.setImageBitmap(bm);
            sCurrentImage = bm;
            sPinchZoomExample = pze;
            //Fit to screen.
            float scale;
            if ((displayHeight / bm.getHeight()) >= (displayWidth / bm.getWidth())){
                scale =  (float)displayWidth / (float)bm.getWidth();
            } else {
                scale = (float)displayHeight / (float)bm.getHeight();
            }

            savedMatrix.set(matrix);
            matrix.set(savedMatrix);
            matrix.postScale(scale, scale, mid.x, mid.y);
            setImageMatrix(matrix);


            // Center the image
            float redundantYSpace = (float)displayHeight - (scale * (float)bm.getHeight()) ;
            float redundantXSpace = (float)displayWidth - (scale * (float)bm.getWidth());

            redundantYSpace /= (float)2;
            redundantXSpace /= (float)2;


            savedMatrix.set(matrix);
            matrix.set(savedMatrix);
            matrix.postTranslate(redundantXSpace, redundantYSpace);   //matrix.postTranslate(50, 50);
            setImageMatrix(matrix);


        }




        /** Determine the space between the first two fingers */
        private float spacing(WrapMotionEvent 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, WrapMotionEvent event) {
            // ...
            float x = event.getX(0) + event.getX(1);
            float y = event.getY(0) + event.getY(1);
            point.set(x / 2, y / 2);
        }

}

Upvotes: 9

Views: 13338

Answers (4)

Tayyab Javed
Tayyab Javed

Reputation: 9

Create a temporary matrix (temp), save the current matrix in it and scal the temp matrix. Then check the MSCALE_X value of temp matrix.

If zoom of your temp matrix is within your limit, postscale your matrix and save it in another matrix (savedMatrixZoom). If it is over your limit just load your current matrix from SavedMatrixZoom.

    else if (mode == ZOOM) {
        float newDist = spacing(event);
        Log.d(TAG, "newDist=" + newDist);
        if (newDist > 10f) {
            matrix.set(savedMatrix);
            zoomScale = newDist / oldDist;

            Matrix temp = new Matrix();
            temp.set(matrix);
            temp.postScale(zoomScale, zoomScale, mid.x, mid.y);
            mapZoom = getValue(temp, Matrix.MSCALE_X);
            if (mapZoom < MAX_ZOOM && mapZoom > MIN_ZOOM) {
                matrix.postScale(zoomScale, zoomScale, mid.x, mid.y);
                savedMatrixZoom.set(matrix);
            } else {
                matrix.set(savedMatrixZoom);
            }
        }
    }

Hope it helps

Upvotes: 0

Arjun
Arjun

Reputation: 371

Check my answer here. It worked with very little extra coding effort.

https://stackoverflow.com/a/18395969/2709830

Upvotes: 3

nagaraj
nagaraj

Reputation: 159

if(mapZoom > MAX_ZOOM && (newDist > oldDist) ) {
    break;
} else if(mapZoom < MIN_Zoom && (newDist < oldDist) ){
    break;
}

matrix.postScale(zoomScale, zoomScale, mid.x, mid.y);  
savedMatrixZoom.set(matrix);  

It works fine but still I loose that smoothness and is too sensitive.

Upvotes: 0

Akos Cz
Akos Cz

Reputation: 12790

private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 5.0f;

scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));

Upvotes: 7

Related Questions