Skip to content Skip to sidebar Skip to footer

Imageview Drag Limitation In Android

I have an ImageView in a layout and set OnTouchListener on ImageView to drag the ImageView. It's working perfectly. My problem is how can I prevent from move ImageView to out of la

Solution 1:

Add the following parameters to the Touch class:

privatefloat dx; // postTranslate X distanceprivatefloat dy; // postTranslate Y distanceprivatefloat[] matrixValues = newfloat[9];
float matrixX = 0; // X coordinate of matrix inside the ImageViewfloat matrixY = 0; // Y coordinate of matrix inside the ImageViewfloat width = 0; // width of drawablefloat height = 0; // height of drawable

Modify your code after case MotionEvent.ACTION_MOVE:

if (mode == DRAG) {
        matrix.set(savedMatrix);

        matrix.getValues(matrixValues);
        matrixX = matrixValues[2];
        matrixY = matrixValues[5];
        width = matrixValues[0] * (((ImageView) view).getDrawable()
                                .getIntrinsicWidth());
        height = matrixValues[4] * (((ImageView) view).getDrawable()
                                .getIntrinsicHeight());

        dx = event.getX() - start.x;
        dy = event.getY() - start.y;

        //if image will go outside left boundif (matrixX + dx < 0){
            dx = -matrixX;
        }
        //if image will go outside right boundif(matrixX + dx + width > view.getWidth()){
            dx = view.getWidth() - matrixX - width;
        }
        //if image will go oustside top boundif (matrixY + dy < 0){
            dy = -matrixY;
        }
        //if image will go outside bottom boundif(matrixY + dy + height > view.getHeight()){
            dy = view.getHeight() - matrixY - height;
        }
        matrix.postTranslate(dx, dy);   
    }

Solution 2:

Android documentation says:

It is possible to retrieve the location of a view by invoking the methods getLeft() and getTop(). The former returns the left, or X, coordinate of the rectangle representing the view. The latter returns the top, or Y, coordinate of the rectangle representing the view. These methods both return the location of the view relative to its parent. In addition, several convenience methods are offered to avoid unnecessary computations, namely getRight() and getBottom(). These methods return the coordinates of the right and bottom edges of the rectangle representing the view. For instance, calling getRight() is similar to the following computation: getLeft() + getWidth().

So you can get your image coordinates before moving it,and you can compute measure of movement in your OnTouchListener class.Now if (X coordinate of your image plus horizontal movement that you computed,be greater than device width or Y coordinate of your image plus vertical movement that you computed,be greater than device height) your image not move.

Solution 3:

I used the answer from Benito Bertoli and modified the ACTION_MOVE code changing minor and major sign to make image zoom and drag for image zoomed

here´s the code

privatestatic final float MIN_ZOOM = 1f; 
privatestatic final float MAX_ZOOM = 2.5f; 

public boolean onTouch(View v, MotionEvent event) {
    ImageView view = (ImageView) v;
    view.setScaleType(ImageView.ScaleType.MATRIX);

    // Handle touch events here...switch (event.getAction() & MotionEvent.ACTION_MASK) {

        case MotionEvent.ACTION_DOWN: //first finger down only
            savedMatrix.set(matrix);
            start.set(event.getX(), event.getY());
            Log.d(TAG, "mode=DRAG" );
            mode = DRAG;
            break;
        case MotionEvent.ACTION_UP: //first finger liftedcase MotionEvent.ACTION_POINTER_UP: //second finger lifted
            mode = NONE;
            Log.d(TAG, "mode=NONE" );
            break;
        case MotionEvent.ACTION_POINTER_DOWN: //second finger 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_MOVE:
            if (mode == DRAG) {
                //matrix.set(savedMatrix);//matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
                matrix.set(savedMatrix);

                matrix.getValues(matrixValues);
                matrixX = matrixValues[2];
                matrixY = matrixValues[5];
                width = matrixValues[0] * (view.getDrawable().getIntrinsicWidth());
                height = matrixValues[4] * (view.getDrawable().getIntrinsicHeight());


                dx = event.getX() - start.x;
                dy = event.getY() - start.y;

                //if image will go outside left boundif (matrixX + dx  > 0){
                    Log.e("dx","lef bound " + dx);
                    dx = -matrixX;
                }
                //if image will go outside right boundif(matrixX + dx + width < view.getWidth()){
                    dx = view.getWidth() - matrixX - width;
                }
                //if image will go oustside top boundif (matrixY + dy > 0){
                    dy = -matrixY;
                }
                //if image will go outside bottom boundif(matrixY + dy + height < view.getHeight()){
                    dy = view.getHeight() - matrixY - height;
                }

                matrix.postTranslate(dx, dy);
            }
            elseif (mode == ZOOM) {
                Float newDist = spacing(event);
                Log.d(TAG, "newDist=" + newDist);
                if (newDist > 10f) {
                    matrix.set(savedMatrix);
                    float scale = newDist / oldDist;
                    float[] values = newfloat[9];
                    matrix.getValues(values);
                    float currentScale = values[Matrix.MSCALE_X];
                    if(scale * currentScale > MAX_ZOOM)
                        scale = MAX_ZOOM / currentScale;
                    elseif (scale * currentScale < MIN_ZOOM)
                        scale = MIN_ZOOM / currentScale;
                    matrix.postScale(scale, scale, mid.x, mid.y);

                }
                break;
            }
    } //perform the transformation.

    view.setImageMatrix(matrix);
    returntrue; // indicate event was handled

}

privatefloatspacing(MotionEvent event) {
    float x = event.getX(0) - event.getX(1);
    float y = event.getY(0) - event.getY(1);
    return (float)Math.sqrt(x * x + y * y);
}

privatevoidmidPoint(PointF point, MotionEvent event) {
    float x = event.getX(0) + event.getX(1);
    float y = event.getY(0) + event.getY(1);
    point.set(x / 2, y / 2);
}

    return drawable;
}

Solution 4:

  1. We need to create two Rect objects, one is for our view and another for our image according to the view coordinates.

    float[] values=newfloat[9];
    matrix.getValues(values);
    float globalX =values[Matrix.MTRANS_X];
    float globalY =values[Matrix.MTRANS_Y];
    float scaleX =values[Matrix.MSCALE_X];
    float scaleY =values[Matrix.MSCALE_Y];
    Rect viewRect =new Rect(0, 0, viewWidth, viewHeight);
    Rect imageRect =new Rect((int) globalX, (int) globalY, Math.round(bitmapWidth * scaleX + globalX),
            Math.round(bitmapHeight * scaleY + globalY));
    
    1. If we want our image be always inside our view, then we check this:

      if (!viewRect.contains(imageRect)) {
          matrix.set(lastSetMatrix); //return to last saved parameters
      }
      
    2. Sometimes we need our image always be bigger than our view to position a part of the image inside the view, then we can check this:

      if (!imageRect.contains(viewRect)) {
         matrix.set(lastSetMatrix);
      }
      

Solution 5:

I have done this code. when I zoom hen it should not go out of boundry. its working fine.But when it touches cordinate of x=0 and y=0 it do not minimize.

int FLAG=0;   



 elseif (mode == ZOOM) {

                    float newDistance = spacing(event);

                    Log.i("new distance ", newDistance+"");

                    matrix.getValues(matrixValues);
                    matrixX = matrixValues[2];
                    matrixY = matrixValues[5];
                    width = matrixValues[0]
                            * (((ImageView) view).getDrawable().getIntrinsicWidth());
                    height = matrixValues[4]
                            * (((ImageView) view).getDrawable()
                                    .getIntrinsicHeight());

                    dx = event.getX() - start.x;
                    dy = event.getY() - start.y;

                    // if image will go outside left boundif (matrixX + dx < 0) {
                        FLAG=1;
                    }
                    if (matrixX + dx + width > view.getWidth()) {
                        FLAG=1;
                        //dx = view.getWidth() - matrixX - width;
                    }
                    // if image will go oustside top boundif (matrixY + dy < 0) {
                        FLAG=1;
                        //dy = -matrixY;
                    }
                    // if image will go outside bottom boundif (matrixY + dy + height > view.getHeight()) {
                        FLAG=1;
                        //dy = view.getHeight() - matrixY - height;
                    }
                if (matrixX + dx ==0 || matrixY + dy==0){ 
                    FLAG=0;
                }

                    if (newDistance > 10f && FLAG==0) {

                        matrix.set(savedMatrix);

                        float scale = newDistance / oldDistance;

                        float[] values = newfloat[9];

                        matrix.getValues(values);
                        float currentScale = values[Matrix.MSCALE_X];
                        if (scale * currentScale > MAX_ZOOM)
                            scale = MAX_ZOOM / currentScale;
                        elseif (scale * currentScale < MIN_ZOOM)
                            scale = MIN_ZOOM / currentScale;
                        matrix.postScale(scale, scale, mid.x, mid.y);
                    }
                }
                break;

Post a Comment for "Imageview Drag Limitation In Android"