"Zoom In/out " image on Button Click in Android?
Solution 1
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.
Solution 2
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);
Solution 3
Try to use PhotoView. I think it does what you want out of the box.
user3233280
Updated on June 25, 2022Comments
-
user3233280 almost 2 years
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
-
user3233280 over 10 yearshow can i max and min zoom level >
-
Mohammed Alokshiya over 10 yearsBy using build-in (-/+) zooming controllers supported by webView. here is an example: link. Or if you want to set initial zoom level, use the method: mWebView.setInitialScale(50); with input value between 0 - 100 (%).
-
user3233280 over 10 yearscan u please help me i want to fixed header and footer while i need to place "ImageView" in Scroll View i have done this but sometimes my imageview is too short and footer disappear
-
user3233280 over 10 yearsHere is my xml can u please edit this in order to show images more clearly but header and footer should be fixed
-
user3233280 over 10 yearshere imageView of touch is a very small size and its appearing in center
-
Erum almost 10 years@MrSMAK can u please help me how can i write same code of zoomin and zoomout buttons for paging.i am using paging and on every page there will be a image and zoomin and zoomout buttons.Where will i write code for zoomin and zoomout buttons may i need to write zoomin and zoomout btns functionality inside this method: public Object instantiateItem(ViewGroup container, int position) {}
-
Salman Khakwani almost 10 years@ErumHannan This link explains exactly what you are looking for : androidtutorialpoints.blogspot.com/2013/10/…
-
Erum almost 10 yearscan someone please help me i have two buttons on top and in center i have imageview and in footer i have again 3 buttons now center imageview will contain different image for every pager for page1 there is image1 and for page2 there is page2 and now for every image these top buttons and footer buttons should be used for zoomin and zoomout now my question is where should i write button events in java.may i need to write in this method : @Override public View instantiateItem(ViewGroup container, int position) { PhotoView photoView = new PhotoView(container.getContext());
-
Erum almost 10 years@MrSMAK can u please help me for zoomin and zoomout i am using TouchImageView.My question is where should i write zoomin and zoomout button code inside of this method : public View instantiateItem(ViewGroup container, int position) { PhotoView photoView = new PhotoView(container.getContext());
-
Salman Khakwani almost 10 yearsStep#1: Take a chill pill ^_^ Step#2: Download this code github.com/AndroidAk/ImageGallerywithzoom Step#3: Run this Project on your device and see if this is what you are looking for ?
-
Erum almost 10 yearsi am failed to run this project in android
-
Erum almost 10 years@MrSMAK this is not being import in eclipse
-
Salman Khakwani almost 10 yearsPlease paste the errors that are shown in the Errors Tab in your Eclipse.
-
Software Prophets over 9 yearsIt definitely works, so I'm up voting, but note some differences from displaying an image in an ImageView: 1) Image in ImageView resizes automatically to fit the size of the view and 2) there are easy options to center the image in an ImageView.
-
Vishal Thakkar about 3 yearsnot working for me i am not able to load image inside imageview dont know why.