ImageView Drag Limitation In Android

前端 未结 5 1652
遇见更好的自我
遇见更好的自我 2021-02-09 06:21

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 o

相关标签:
5条回答
  • 2021-02-09 06:32

    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

    private static final float MIN_ZOOM = 1f; 
    private static 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 lifted
            case 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 bound
                    if (matrixX + dx  > 0){
                        Log.e("dx","lef bound " + dx);
                        dx = -matrixX;
                    }
                    //if image will go outside right bound
                    if(matrixX + dx + width < view.getWidth()){
                        dx = view.getWidth() - matrixX - width;
                    }
                    //if image will go oustside top bound
                    if (matrixY + dy > 0){
                        dy = -matrixY;
                    }
                    //if image will go outside bottom bound
                    if(matrixY + dy + height < view.getHeight()){
                        dy = view.getHeight() - matrixY - height;
                    }
    
                    matrix.postTranslate(dx, dy);
                }
                else if (mode == ZOOM) {
                    Float newDist = spacing(event);
                    Log.d(TAG, "newDist=" + newDist);
                    if (newDist > 10f) {
                        matrix.set(savedMatrix);
                        float scale = newDist / oldDist;
                        float[] values = new float[9];
                        matrix.getValues(values);
                        float currentScale = values[Matrix.MSCALE_X];
                        if(scale * currentScale > MAX_ZOOM)
                            scale = MAX_ZOOM / currentScale;
                        else if (scale * currentScale < MIN_ZOOM)
                            scale = MIN_ZOOM / currentScale;
                        matrix.postScale(scale, scale, mid.x, mid.y);
    
                    }
                    break;
                }
        } //perform the transformation.
    
        view.setImageMatrix(matrix);
        return true; // indicate event was handled
    
    }
    
    private float spacing(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);
    }
    
    private void midPoint(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;
    }
    
    0 讨论(0)
  • 2021-02-09 06:43

    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.

    0 讨论(0)
  • 2021-02-09 06:43

    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;   
    
    
    
     else if (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 bound
                        if (matrixX + dx < 0) {
                            FLAG=1;
                        }
                        if (matrixX + dx + width > view.getWidth()) {
                            FLAG=1;
                            //dx = view.getWidth() - matrixX - width;
                        }
                        // if image will go oustside top bound
                        if (matrixY + dy < 0) {
                            FLAG=1;
                            //dy = -matrixY;
                        }
                        // if image will go outside bottom bound
                        if (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 = new float[9];
    
                            matrix.getValues(values);
                            float currentScale = values[Matrix.MSCALE_X];
                            if (scale * currentScale > MAX_ZOOM)
                                scale = MAX_ZOOM / currentScale;
                            else if (scale * currentScale < MIN_ZOOM)
                                scale = MIN_ZOOM / currentScale;
                            matrix.postScale(scale, scale, mid.x, mid.y);
                        }
                    }
                    break;
    
    0 讨论(0)
  • 2021-02-09 06:47

    Add the following parameters to the Touch class:

    private float dx; // postTranslate X distance
    private float dy; // postTranslate Y distance
    private float[] matrixValues = new float[9];
    float matrixX = 0; // X coordinate of matrix inside the ImageView
    float matrixY = 0; // Y coordinate of matrix inside the ImageView
    float width = 0; // width of drawable
    float 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 bound
            if (matrixX + dx < 0){
                dx = -matrixX;
            }
            //if image will go outside right bound
            if(matrixX + dx + width > view.getWidth()){
                dx = view.getWidth() - matrixX - width;
            }
            //if image will go oustside top bound
            if (matrixY + dy < 0){
                dy = -matrixY;
            }
            //if image will go outside bottom bound
            if(matrixY + dy + height > view.getHeight()){
                dy = view.getHeight() - matrixY - height;
            }
            matrix.postTranslate(dx, dy);   
        }
    
    0 讨论(0)
  • 2021-02-09 06:51
    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 = new float[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);
        }
        
    0 讨论(0)
提交回复
热议问题