Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Zoom In/out " image on Button Click in Android?

I am newbie in Android.I have followed this Question and i successfully zoom an image this code is working fine can someone please help me how to write code for zoomin zoomout on button click.I am not getting how to achieve this task

Here is the Tutorial that i followed Tutorial Zoom Image and also follow "Salman's Ayub Answer"

Its working fine but i am failed to apply scale factor on zoom in and zoom out of image

like image 226
user3233280 Avatar asked Jan 28 '14 18:01

user3233280


People also ask

How to zoom in and zoom out an Android imageview?

This example demonstrates how do I Zoom In and Zoom Out an android ImageView. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main.xml. Step 3 − Add the following code to src/MainActivity.java

How do i Zoom in and zoom out on the screen?

A Toast is displayed to show the zoom in and zoom out message on the screen. Now run the App and you can see a image on the screen. Click on the image and Zoom Controls button will appear on the screen. Now do Zoom In or Zoom Out the image as you wish.

What is zoom controls in Android Studio?

Zoom Controls Tutorial With Example In Android Studio In Android, Zoom Controls class display simple set of controls that is used for zooming and provides callback to register for events. Zoom Controls has two buttons ZoomIn and ZoomOut which are used to control the zooming functionality. Zoom Controls code in XML:

How to add zoom in/out animation in Android with Kotlin?

How to Add Zoom In/Out Animation in Android 1 Click on File, then New => New Project. 2 Select language as Kotlin. 3 Select the minimum SDK as per your need. More ...


3 Answers

You need to add these 2 methods to your TouchImageView class:

public void zoomIn() {
    oldScale = saveScale;

    if(saveScale<=maxScale)
    {
        saveScale += .5;
        matrix.setScale(saveScale, saveScale);
        setImageMatrix(matrix);
        invalidate();

        // Center the image
        // Center the image
        if(bmHeight>bmWidth)
        {
        redundantXSpace = width - (saveScale * bmWidth);
        redundantXSpace /= 2;
        }
        else 
        {
            redundantYSpace = height - (saveScale * bmHeight) ;
            redundantYSpace /= 2;
        }

        matrix.postTranslate(redundantXSpace , redundantYSpace );
        setImageMatrix(matrix);
        invalidate();
    }
}

public void zoomOut() {

    if(saveScale>=minScale)
    {
        saveScale -= .5;
        matrix.setScale(saveScale, saveScale);
        setImageMatrix(matrix);
        invalidate();

        // Center the image
        if(bmHeight>bmWidth)
        {
        redundantXSpace = width - (saveScale * bmWidth);
        redundantXSpace /= 2;
        }
        else 
        {
            redundantYSpace = height - (saveScale * bmHeight) ;
            redundantYSpace /= 2;
        }
        matrix.postTranslate(redundantXSpace , redundantYSpace );
        setImageMatrix(matrix);
        invalidate();
    }
}

Here is the complete TouchImageView class code, along with these 2 methods:

public class TouchImageView extends ImageView {

public Matrix matrix = new 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;
static final int CLICK = 3;
int mode = NONE;
float oldScale = 1.0f;

// Remember some things for zooming
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 4f;
float[] m;

float redundantXSpace, redundantYSpace;   
float width, height;
float saveScale = 1f;
float right, bottom, origWidth, origHeight, bmWidth, bmHeight;

ScaleGestureDetector mScaleDetector;   
Context context;


public TouchImageView(Context context) {

    super(context);

    super.setClickable(true);

    this.context = context;

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

    matrix.setTranslate(1f, 1f);

    m = new float[9];
    setImageMatrix(matrix);
    setScaleType(ScaleType.MATRIX);

    setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            mScaleDetector.onTouchEvent(event);

            matrix.getValues(m);
            float x = m[Matrix.MTRANS_X];
            float y = m[Matrix.MTRANS_Y];
            PointF curr = new PointF(event.getX(), event.getY());

            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = DRAG;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = ZOOM;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == ZOOM || (mode == DRAG && saveScale > minScale)) {
                    Log.d("******", "ZOOM OR DRAG");
                    float deltaX = curr.x - last.x;
                    float deltaY = curr.y - last.y;
                    float scaleWidth = Math.round(origWidth * saveScale);
                    float scaleHeight = Math.round(origHeight * saveScale);
                    if (scaleWidth < width) {
                        deltaX = 0;
                        if (y + deltaY > 0)
                            deltaY = -y;
                        else if (y + deltaY < -bottom)
                            deltaY = -(y + bottom);
                    } else if (scaleHeight < height) {
                        deltaY = 0;
                        if (x + deltaX > 0)
                            deltaX = -x;
                        else if (x + deltaX < -right)
                            deltaX = -(x + right);
                    } else {
                        if (x + deltaX > 0)
                            deltaX = -x;
                        else if (x + deltaX < -right)
                            deltaX = -(x + right);

                        if (y + deltaY > 0)
                            deltaY = -y;
                        else if (y + deltaY < -bottom)
                            deltaY = -(y + bottom);
                    }
                    matrix.postTranslate(deltaX, deltaY);
                    last.set(curr.x, curr.y);
                }else if(mode == DRAG && saveScale == minScale) {
                    Log.d("******", "DRAG");
                }
                break;

            case MotionEvent.ACTION_UP:
                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();
                break;

            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
            }
            setImageMatrix(matrix);
            invalidate();
            return true; // indicate event was handled
        }

    });
}

@Override
public void setImageBitmap(Bitmap bm) {
    super.setImageBitmap(bm);
    bmWidth = bm.getWidth();
    bmHeight = bm.getHeight();
}

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)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05);
        float origScale = saveScale;
        saveScale *= mScaleFactor;
        if (saveScale > maxScale) {
            saveScale = maxScale;
            mScaleFactor = maxScale / origScale;
        } else if (saveScale < minScale) {
            saveScale = minScale;
            mScaleFactor = minScale / origScale;
        }
        right = width * saveScale - width - (2 * redundantXSpace * saveScale);
        bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
        if (origWidth * saveScale <= width || origHeight * saveScale <= height) {
            matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
            if (mScaleFactor < 1) {
                matrix.getValues(m);
                float x = m[Matrix.MTRANS_X];
                float y = m[Matrix.MTRANS_Y];
                if (mScaleFactor < 1) {
                    if (Math.round(origWidth * saveScale) < width) {
                        if (y < -bottom)
                            matrix.postTranslate(0, -(y + bottom));
                        else if (y > 0)
                            matrix.postTranslate(0, -y);
                    } else {
                        if (x < -right)
                            matrix.postTranslate(-(x + right), 0);
                        else if (x > 0)
                            matrix.postTranslate(-x, 0);
                    }
                }
            }
        } else {
            matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
            matrix.getValues(m);
            float x = m[Matrix.MTRANS_X];
            float y = m[Matrix.MTRANS_Y];
            if (mScaleFactor < 1) {
                if (x < -right)
                    matrix.postTranslate(-(x + right), 0);
                else if (x > 0)
                    matrix.postTranslate(-x, 0);
                if (y < -bottom)
                    matrix.postTranslate(0, -(y + bottom));
                else if (y > 0)
                    matrix.postTranslate(0, -y);
            }
        }
        return true;

    }
}

@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    width = MeasureSpec.getSize(widthMeasureSpec);
    height = MeasureSpec.getSize(heightMeasureSpec);
    //Fit to screen.
    float scale;
    float scaleX =  width / bmWidth;
    float scaleY = height / bmHeight;
    scale = Math.min(scaleX, scaleY);
    matrix.setScale(scale, scale);
    setImageMatrix(matrix);
    saveScale = 1f;

    // Center the image
    redundantYSpace = height - (scale * bmHeight) ;
    redundantXSpace = width - (scale * bmWidth);
    redundantYSpace /= 2;
    redundantXSpace /= 2;

    matrix.postTranslate(redundantXSpace, redundantYSpace);

    origWidth = width - 2 * redundantXSpace;
    origHeight = height - 2 * redundantYSpace;
    right = width * saveScale - width - (2 * redundantXSpace * saveScale);
    bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
    setImageMatrix(matrix);
}

public TouchImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    super.setClickable(true);
    this.context = context;
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    matrix.setTranslate(1f, 1f);
    m = new float[9];
    setImageMatrix(matrix);
    setScaleType(ScaleType.MATRIX);

    setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            mScaleDetector.onTouchEvent(event);

            matrix.getValues(m);
            float x = m[Matrix.MTRANS_X];
            float y = m[Matrix.MTRANS_Y];
            PointF curr = new PointF(event.getX(), event.getY());

            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = DRAG;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = ZOOM;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == ZOOM || (mode == DRAG && saveScale > minScale)) {
                    Log.d("******", "ZOOM OR DRAG");
                    float deltaX = curr.x - last.x;
                    float deltaY = curr.y - last.y;
                    float scaleWidth = Math.round(origWidth * saveScale);
                    float scaleHeight = Math.round(origHeight * saveScale);
                    if (scaleWidth < width) {
                        deltaX = 0;
                        if (y + deltaY > 0)
                            deltaY = -y;
                        else if (y + deltaY < -bottom)
                            deltaY = -(y + bottom);
                    } else if (scaleHeight < height) {
                        deltaY = 0;
                        if (x + deltaX > 0)
                            deltaX = -x;
                        else if (x + deltaX < -right)
                            deltaX = -(x + right);
                    } else {
                        if (x + deltaX > 0)
                            deltaX = -x;
                        else if (x + deltaX < -right)
                            deltaX = -(x + right);

                        if (y + deltaY > 0)
                            deltaY = -y;
                        else if (y + deltaY < -bottom)
                            deltaY = -(y + bottom);
                    }
                    matrix.postTranslate(deltaX, deltaY);
                    last.set(curr.x, curr.y);
                }else if(mode == DRAG && saveScale == minScale) {
                    Log.d("******", "DRAG");
                }
                break;

            case MotionEvent.ACTION_UP:
                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();
                break;

            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
            }
            setImageMatrix(matrix);
            invalidate();
            return true; // indicate event was handled
        }

    });
}

public TouchImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    super.setClickable(true);
    this.context = context;
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    matrix.setTranslate(1f, 1f);
    m = new float[9];
    setImageMatrix(matrix);
    setScaleType(ScaleType.MATRIX);

    setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            mScaleDetector.onTouchEvent(event);

            matrix.getValues(m);
            float x = m[Matrix.MTRANS_X];
            float y = m[Matrix.MTRANS_Y];
            PointF curr = new PointF(event.getX(), event.getY());

            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = DRAG;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = ZOOM;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == ZOOM || (mode == DRAG && saveScale > minScale)) {
                    Log.d("******", "ZOOM OR DRAG");
                    float deltaX = curr.x - last.x;
                    float deltaY = curr.y - last.y;
                    float scaleWidth = Math.round(origWidth * saveScale);
                    float scaleHeight = Math.round(origHeight * saveScale);
                    if (scaleWidth < width) {
                        deltaX = 0;
                        if (y + deltaY > 0)
                            deltaY = -y;
                        else if (y + deltaY < -bottom)
                            deltaY = -(y + bottom);
                    } else if (scaleHeight < height) {
                        deltaY = 0;
                        if (x + deltaX > 0)
                            deltaX = -x;
                        else if (x + deltaX < -right)
                            deltaX = -(x + right);
                    } else {
                        if (x + deltaX > 0)
                            deltaX = -x;
                        else if (x + deltaX < -right)
                            deltaX = -(x + right);

                        if (y + deltaY > 0)
                            deltaY = -y;
                        else if (y + deltaY < -bottom)
                            deltaY = -(y + bottom);
                    }
                    matrix.postTranslate(deltaX, deltaY);
                    last.set(curr.x, curr.y);
                }else if(mode == DRAG && saveScale == minScale) {
                    Log.d("******", "DRAG");
                }
                break;

            case MotionEvent.ACTION_UP:
                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();
                break;

            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
            }
            setImageMatrix(matrix);
            invalidate();
            return true; // indicate event was handled
        }

    });
}

public void zoomIn() {
    oldScale = saveScale;

    if(saveScale<=maxScale)
    {
        saveScale += .5;
        matrix.setScale(saveScale, saveScale);
        setImageMatrix(matrix);
        invalidate();

        // Center the image
        // Center the image
        if(bmHeight>bmWidth)
        {
        redundantXSpace = width - (saveScale * bmWidth);
        redundantXSpace /= 2;
        }
        else 
        {
            redundantYSpace = height - (saveScale * bmHeight) ;
            redundantYSpace /= 2;
        }

        matrix.postTranslate(redundantXSpace , redundantYSpace );
        setImageMatrix(matrix);
        invalidate();
    }
}

public void zoomOut() {

    if(saveScale>=minScale)
    {
        saveScale -= .5;
        matrix.setScale(saveScale, saveScale);
        setImageMatrix(matrix);
        invalidate();

        // Center the image
        if(bmHeight>bmWidth)
        {
        redundantXSpace = width - (saveScale * bmWidth);
        redundantXSpace /= 2;
        }
        else 
        {
            redundantYSpace = height - (saveScale * bmHeight) ;
            redundantYSpace /= 2;
        }
        matrix.postTranslate(redundantXSpace , redundantYSpace );
        setImageMatrix(matrix);
        invalidate();
    }
}
} 

Here how you can use them in your zoomIn/zoomOut buttons:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.LAYOUT_NAME);

    Button zoonIn = (Button)findViewById(R.id.ZOOM_IN_BUTTON_ID);
    Button zoonOut = (Button)findViewById(R.id.ZOOM_OUT_BUTTON_ID);

    final TouchImageView touch = (TouchImageView)findViewById(R.id.YOUR_TOUCH_IMAGE_VIEW_)ID);

    Bitmap bImage = BitmapFactory.decodeResource(this.getResources(), R.drawable.DRAWABLE_ID);

    touch.setImageBitmap(bImage);

    touch.setMaxZoom(4f); //change the max level of zoom, default is 3f


    zoonIn.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            touch.zoomIn();
        }
    });


    zoonOut.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            touch.zoomOut();
        }
    });

}

I hope this helps.

like image 199
Salman Khakwani Avatar answered Oct 09 '22 03:10

Salman Khakwani


The easiest way to zoom in/out images on button, is to display it in a webView, then you can use all features offered by webView.

copy your image in assets folder, then load it in onCreate:

WebView mWebView = (WebView) findViewById(R.id.webView1);
mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
mWebView.setBackgroundColor(Color.parseColor("#ffffff"));
mWebView.loadUrl("file:///android_asset/image.png");
mWebView.getSettings().setBuiltInZoomControls(true);
mWebView.setInitialScale(50);
like image 30
Mohammed Alokshiya Avatar answered Oct 09 '22 01:10

Mohammed Alokshiya


Try to use PhotoView. I think it does what you want out of the box.

like image 41
Leonidos Avatar answered Oct 09 '22 02:10

Leonidos