6

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  
}
Jack B Nimble
  • 5,039
  • 4
  • 40
  • 62
user958880
  • 487
  • 1
  • 7
  • 18

2 Answers2

2

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);
      }
   ...
brk3
  • 1,524
  • 2
  • 19
  • 31
  • 1
    So would the `break;` statement solve it? I have a question here: http://stackoverflow.com/questions/21520075/how-to-keep-x-and-y-within-layouts-view. – Si8 Feb 03 '14 at 14:55
  • 1
    Hey may i know what is start here? – Mayank Saini Mar 07 '14 at 06:44
  • it doesn't work. newX just shows the difference of the starting point and the end point of the drag action. it easily gets negative while the image is still inside the border. – Mohsen Kamrani Dec 07 '15 at 17:20
1
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;
    }
Philip Herbert
  • 4,599
  • 2
  • 37
  • 40