Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep an image inside the screen limits while using pinch zoom and drag gestures?

I'm building an app that uses the pinch zoom and drag. The problem is that for now I can drag the picture out of it bounds. I wanted to know how can I use drag and make sure the image stays on the screen at the same time.

Here is my code :

public boolean onTouch(View v, MotionEvent event) {
      ImageView view = (ImageView)v;
      //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:
       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 temp = new Matrix();
                 temp.set(matrix);
                 temp.postScale(scale, scale, mid.x, mid.y);
                 float[] f = new float[9];
                 temp.getValues(f);
                 Float xScale = f[0];
                 if(xScale >= 1 && xScale <= 10){
                     matrix.postScale(scale, scale, mid.x, mid.y);
                     savedMatrixZoom.set(matrix);
                 }else{
                     matrix.set(savedMatrixZoom);

              }

              }
          break;
          }       
     } //perform the transformation.

     view.setImageMatrix(matrix);
     return true; // indicate event was handled  
}
like image 957
user958880 Avatar asked Sep 23 '11 16:09

user958880


2 Answers

Why not grab the dimensions of the screen and check the MotionEvent coordinates are within these before updating your matrix?

Something like..

DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int screenHight = displaymetrics.heightPixels;
int screenWidth = displaymetrics.widthPixels;

   ...
   case MotionEvent.ACTION_MOVE:

      if (mode == DRAG) {

         int newX = event.getX() - start.x;
         int newY = event.getY() - start.y;
         if ( (newX <= 0 || newX >= screenWidth) ||
              (newY <= 0 || newY >= screenHeight) )
             break;

         matrix.set(savedMatrix);
         matrix.postTranslate(newX, newY);
      }
   ...
like image 134
brk3 Avatar answered Nov 16 '22 03:11

brk3


public boolean onTouch(View v, MotionEvent event) {
        int action = event.getAction();

        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int sH = displaymetrics.heightPixels;
        int sW = displaymetrics.widthPixels;
        float dx, dy, newX, newY;

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                dx = event.getRawX() - v.getX();
                dy = event.getRawY() - v.getY();
                break;

            case MotionEvent.ACTION_MOVE:
                newX = event.getRawX() - dx;
                newY = event.getRawY() - dy;

                if ((newX <= 0 || newX >= sW-v.getWidth()) || (newY <= 0 || newY >= sH-v.getHeight()))
                    break;

                v.setX(newX);
                v.setY(newY);
                break;   

            default:
                break;
        }

        return true;
    }
like image 31
Philip Herbert Avatar answered Nov 16 '22 02:11

Philip Herbert