12

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?

Piotr Niewinski
  • 1,298
  • 2
  • 15
  • 27
Audum
  • 219
  • 2
  • 3
  • 5

4 Answers4

22

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);
    }
}
....        
Vect0r
  • 66
  • 1
  • 4
Arjun
  • 361
  • 2
  • 4
3

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);
}
Sico Syco
  • 31
  • 2
3

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.

Li_W
  • 759
  • 1
  • 5
  • 15
  • You have the right idea calling `matrix.getValues(f);`. However, the solution is not to return true, as this will simply freeze the screen. Rather if the scaling value is about to surpass the MAX_SCALE, then set the scaling value equal to the MAX_SCALE. Check my answer below for a full implementation using this method. – Mike Ortiz Oct 04 '11 at 08:18
2

I provided an answer here that adds panning, zoom, and boundary detection to ImageView.

Community
  • 1
  • 1
Mike Ortiz
  • 4,031
  • 4
  • 27
  • 54