Home » Android » Scale limits on pinch zoom of android

Scale limits on pinch zoom of android

Posted by: admin June 15, 2020 Leave a comment

Questions:

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);
        }

}
How to&Answers:
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));

Answer:

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

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

Answer:

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.

Answer:

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