I wanted to create a gallery with images. The images within the gallery should be zoomable and pannable. I could able to pinch-zoom an image but could not able to set zoom limits and prevent the image from being panned off the screen. I used the following code to zoom an image:
First approach : I used TouchImageView to supply images to the gallery, this allows me to pinch-zoom but I can't scroll the gallery, i.e. I can't differentiate between 'single tab event' and 'tab to scroll event'.
Second approach : Used ImageView to supply images to gallery, and if user clicks on any of the gallery items display the selected image in TouchImageView, where the user can Pinch-Zoom an image. But this also prevents me from scrolling the gallery view. And also how to set zoom limits and pan bounds on the selected image?
An Image View with touch can be used to make a great tool that provides zooming and panning an image inside it. So that the user can view very large images inside a small screen. In Android, we all have seen the built-in Gallery.
Default value: 1. * @param min min zoom multiplier. * Reset zoom and translation to initial state. * Set zoom to the specified scale. Image will be centered by default.
You will be building an app that have an Android ImageView and a TextView, when you tap on the ImageView an Android Alertdialog will appear on the screen showing you the image in full size where you can pinch and zoom on the image itself.
// OnTouchImageViewListener is set: TouchImageView pinch zoomed by user. * an animated zoom in/out graphic to the image. // with every frame. * of the zoom.
This fixed the zoom-limit problem for me. After the image is zoomed in/out to the limit, it just stops going further. It's also smooth and there are no lags. 0.7 and 2.0 are the minimum and maximum zoom levels.
....
} else if (mode == ZOOM) {
float[] f = new float[9];
float newDist = spacing(event);
if (newDist > 10f) {
matrix.set(savedMatrix);
float tScale = newDist / dist;
matrix.postScale(tScale, tScale, mid.x, mid.y);
}
matrix.getValues(f);
float scaleX = f[Matrix.MSCALE_X];
float scaleY = f[Matrix.MSCALE_Y];
if(scaleX <= 0.7f) {
matrix.postScale((0.7f)/scaleX, (0.7f)/scaleY, mid.x, mid.y);
} else if(scaleX >= 2.5f) {
matrix.postScale((2.5f)/scaleX, (2.5f)/scaleY, mid.x, mid.y);
}
}
....
You can set zoom limit by adding these lines to ACTION_MOVE, mode == ZOOM:
float[] f = new float[9];
matrix.getValues(f);
float scaleX = f[Matrix.MSCALE_X];
float scaleY = f[Matrix.MSCALE_Y];
if (scaleX > MAX_SCALE || scaleY > MAX_SCALE) return true;
Similarly, add lines to ACTION_MOVE, mode == DRAG that takes into account the original location of your image, the translated length, and then compare them to the bounds.
Have tried using this code below and although it works I found that it was causing small incremental values to accumulate in Trans X and Trans Y leading to the picture slowly moving off screen.
if(scaleX <= 0.7f)
matrix.postScale((0.7f)/scaleX, (0.7f)/scaleY, mid.x, mid.y);
else if(scaleX >= 2.5f)
matrix.postScale((2.5f)/scaleX, (2.5f)/scaleY, mid.x, mid.y);
I fixed this be storing an original matrix in a float[] (1,0,0,0,1,0,0,0,1) and resetting the matrix back to these values whenever scaleX < 1. Hope this helps someone else one day :)
if(scaleX <= 1.0f) {
float[] originalmatrixvalues = new float[] {1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f};
matrix.setValues(originalmatrixvalues);
} else if(scaleX >= 2.5f) {
matrix.postScale((2.5f)/scaleX, (2.5f)/scaleY, mid.x, mid.y);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With