How do I modify TouchImageView with double tap to zoom in and out?

后端 未结 5 766
无人及你
无人及你 2020-12-29 17:37

I am modifying the TouchImageView (https://github.com/MikeOrtiz/TouchImageView/issues) to have zoom in and out for when you double tap. I have started as per this post - How

相关标签:
5条回答
  • 2020-12-29 17:43

    Doubles the current zoom to zoom in, then returns to original zoom level:

    float oldScale = 1.0f;
    public void zoomIn() {
        LogUtil.i(TAG, "Zooming in");
        oldScale = saveScale;
        saveScale *= 2;
        matrix.setScale(saveScale, saveScale);
        setImageMatrix(matrix);
        invalidate();
    }
    
    public void zoomOut() {
        LogUtil.i(TAG, "Zooming out");
        saveScale = oldScale;
        matrix.setScale(saveScale, saveScale);
        setImageMatrix(matrix);
        invalidate();
    }
    

    You might want to translate the matrix to centre on the point the user double clicked.

    0 讨论(0)
  • 2020-12-29 17:47

    @sherlock,

    If you want to zoom out when double tap again, you can write a method as below:

    private void handleScaleWhenDoubleTap(float scaleFactor) {
        //set original scale
        float origScale = curScale;
        //update current scale
        curScale *= scaleFactor;
        //fix current scale if it greater than max scale, recalculate scale factor
        if (curScale > maxScale) {
            curScale = maxScale;
            scaleFactor = maxScale / origScale;
        }
        //fix current scale if it less than min scale, recalculate scale factor
        else if (curScale < minScale) {
            curScale = minScale;
            scaleFactor = minScale / origScale;
        }
        //calculate right point, bottom point
        right = (curScale - 1) * width - 2 * (redundantXSpace * curScale);
        bottom = (curScale - 1) * height - 2 * (redundantYSpace * curScale);
        //scale
        matrix.postScale(scaleFactor, scaleFactor, width / 2, height / 2);
        //translate
        matrix.getValues(m);
        float x = m[Matrix.MTRANS_X];
        float y = m[Matrix.MTRANS_Y];
    
        if (y + bottom < 0) {
            if (x >= 0) {
                matrix.postTranslate(-x + redundantXSpace, -(y + bottom + redundantYSpace));
            } else if (x + right < 0) {
                matrix.postTranslate(-(x + right + redundantXSpace), -(y + bottom + redundantYSpace));
            } else {
                matrix.postTranslate(0, -(y + bottom));
            }
        } else if (y >= 0) {
            if (x >= 0) {
                matrix.postTranslate(-x + redundantXSpace, -y + redundantYSpace - navBarHeight);
            } else if (x + right < 0) {
                matrix.postTranslate(-(x + right + redundantXSpace), -y + redundantYSpace - navBarHeight);
            } else {
                matrix.postTranslate(0, -y);
            }
        } else {
            if (x >= 0) {
                matrix.postTranslate(-x, redundantYSpace - navBarHeight);
            } else if (x + right < 0) {
                matrix.postTranslate(-(x + right + redundantXSpace), redundantYSpace - navBarHeight);
            } else {
                matrix.postTranslate(0, -navBarHeight);
            }
        }
    }
    

    Note: In case a phone has Soft Navigation Bar (as Nexus 5), you have to recalculate the distance to translate. In my example, navBarHeight is the variable that be set by the function:

     public int getNavBarHeight(Context ctx) {
            int id = ctx.getResources().getIdentifier("config_showNavigationBar", "bool", "android");
            boolean hasNavBar = id > 0 && ctx.getResources().getBoolean(id);
            if (hasNavBar) {
                int resourceId = ctx.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
                if (resourceId > 0) {
                    return ctx.getResources().getDimensionPixelSize(resourceId);
                }
            }
            return 0;
        }
    

    Let me know if it helps.

    0 讨论(0)
  • 2020-12-29 17:59

    With the class TouchImageView above, if you want to apply Double Tap, you can do some steps:

    1. Declare variable:

      GestureDetector mDoubleTap;
      
    2. Init in constructor:

      mDoubleTap = new GestureDetector(new DoubleTapGestureListener());
      
    3. Register in onTouch():

      @Override
      public boolean onTouch(View v, MotionEvent event) {
          mDoubleTap.onTouchEvent(event);
          ...
      }
      
    4. Write the method handleScale() - coppied from onScale() method - as below:

      private void handleScale(float mScaleFactor) {
          float origScale = saveScale;
          saveScale *= mScaleFactor;
          if (saveScale > maxScale) {
              saveScale = maxScale;
              mScaleFactor = maxScale / origScale;
          } else if (saveScale < minScale) {
              saveScale = minScale;
              mScaleFactor = minScale / origScale;
          }
          right = width * saveScale - width - (2 * redundantXSpace * saveScale);
          bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
          if (origWidth * saveScale <= width || origHeight * saveScale <= height) {
              matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
              if (mScaleFactor < 1) {
                  matrix.getValues(m);
                  float x = m[Matrix.MTRANS_X];
                  float y = m[Matrix.MTRANS_Y];
                  if (mScaleFactor < 1) {
                      if (Math.round(origWidth * saveScale) < width) {
                          if (y < -bottom)
                              matrix.postTranslate(0, -(y + bottom));
                          else if (y > 0)
                              matrix.postTranslate(0, -y);
                      } else {
                          if (x < -right)
                              matrix.postTranslate(-(x + right), 0);
                          else if (x > 0)
                              matrix.postTranslate(-x, 0);
                      }
                  }
              }
          } else {
              matrix.postScale(mScaleFactor, mScaleFactor, mScaleDetector.getFocusX(), mScaleDetector.getFocusY());
              matrix.getValues(m);
              float x = m[Matrix.MTRANS_X];
              float y = m[Matrix.MTRANS_Y];
              if (mScaleFactor < 1) {
                  if (x < -right)
                      matrix.postTranslate(-(x + right), 0);
                  else if (x > 0)
                      matrix.postTranslate(-x, 0);
                  if (y < -bottom)
                      matrix.postTranslate(0, -(y + bottom));
                  else if (y > 0)
                      matrix.postTranslate(0, -y);
              }
          }
      }
      
    5. Put it in zoomIn() method as:

      public void zoomIn() {
          handleScale(2.0f);// 2.0f is the scale ratio
      }
      
    6. In the override method onScale(), you can modify as:

       @Override
          public boolean onScale(ScaleGestureDetector detector) {
              float mScaleFactor = detector.getScaleFactor();
              handleScale(mScaleFactor);
              return true;
          }
      

    to follow DRY principle.

    Note: double tap has only effect with small touched area.

    Let me know if it works for you.

    0 讨论(0)
  • 2020-12-29 18:02

    Double tapping and other gestures can be detected as follows: Fling gesture detection on grid layout

    I hope this helps... Emmanuel

    0 讨论(0)
  • 2020-12-29 18:08

    My answer might be not exactly specific to your problem but it covers ImageView Zooom in/out, double tap, Bounding image in Imageview when its zoomed , In short is exactly like the default Gallery app of Android

    http://blog.sephiroth.it/2011/04/04/imageview-zoom-and-scroll/

    As the blog says:

    As long as Android doesn’t have a built-in ImageView widget with zoom and scroll capabilities I tries to create one by myself starting from the google repository.

    The result is pretty nice so I’m posting here the source code, if anyone is interested, or simply doesn’t want to waste the time creating a new one.

    0 讨论(0)
提交回复
热议问题