2013-08-03 58 views
0

我的問題是最相似的:的Android 4.3的ImageView與ScaleType:MATRIX

Android 4.3 ImageView ScaleType.MATRIX

而且回聲:

android zoom image using matrix

但是,使用的解決方案,這些問題的答案已經解決了我問題。

我正在使用Mike Ortiz的TouchImageView的修改版本來允許雙擊和常規縮放手勢來放大我的ImageView。對於Android 4.2.2及更低版本,註釋掉「setScaleType(ScaleType.MATRIX)」就好了,圖像集中在ImageView中,並且可以隨意放大和縮小。但是,取消註釋會導致ImageView的圖像尺寸不正確。所有這一切都很好,因爲我剛剛離開那條線評論,並且一切正常。

但是,從Android 4.3開始,如果沒有setScaleType(ScaleType.MATRIX),則無法縮放。所以我不得不取消這條評論,但我從未解決的老問題又回來了。

因此,首先,爲什麼當我所做的全部設置ScaleType時,爲什麼我的計算結果無法生成正確的圖像/ ImageView比率?其次,爲什麼它會在沒有設置刻度類型的情況下放大4.2.2,但在4.3上,它不會?最後,有人能給我一些資源來了解更多關於ScaleType.MATRIX的真正用途嗎?我已經閱讀了一些資料,並做了一些Google搜索,但不完全掌握它。

預先感謝您,並在下面的代碼。

public class TouchImageView extends ImageView { 

Matrix matrix = new Matrix(); 

// We can be in one of these 3 states 
static final int NONE = 0; 
static final int DRAG = 1; 
static final int ZOOM = 2; 
int mode = NONE; 

// Remember some things for zooming 
PointF last = new PointF(); 
PointF start = new PointF(); 
float minScale = 1f; 
float maxScale = 10f; 
float[] floatArray; 

float unusedWidth, unusedHeight; 

float imageViewWidth, imageViewHeight; 
float initialScale = 1f; 
float right, bottom, origWidth, origHeight, imageWidth, imageHeight; 

boolean zoomedInLastTime = false; 
PointF zoomCenter; 

ScaleGestureDetector mScaleDetector; 
GestureDetector mDetector; 

Context context; 

public TouchImageView(Context context) { 
    super(context); 
    sharedConstructing(context); 
} 

public TouchImageView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    sharedConstructing(context); 
} 

private void sharedConstructing(Context context) { 
    super.setClickable(true); 
    this.context = context; 
    setScaleType(ScaleType.MATRIX); 
    //matrix = this.getImageMatrix(); 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 

    //this is an empty GestureDetector 
    mDetector = new GestureDetector(this.context, new GestureDetector.OnGestureListener() { 
     @Override 
     public boolean onDown(MotionEvent motionEvent) { 
      return false; 
     } 

     @Override 
     public void onShowPress(MotionEvent motionEvent) { 

     } 

     @Override 
     public boolean onSingleTapUp(MotionEvent motionEvent) { 
      return false; 
     } 

     @Override 
     public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent2, float v, float v2) { 
      return false; 
     } 

     @Override 
     public void onLongPress(MotionEvent motionEvent) { 

     } 

     @Override 
     public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent2, float v, float v2) { 
      return false; 
     } 
    }, null, true); 
    mDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener(){ 

     @Override 
     public boolean onSingleTapConfirmed(MotionEvent motionEvent) { 
      return false; 
     } 

     @Override 
     public boolean onDoubleTap(MotionEvent motionEvent) { 
      Log.d("TouchImageView", "double tap heard"); 
      PointF currentTapLocation = new PointF(motionEvent.getX(), motionEvent.getY()); 
      if (!zoomedInLastTime){ 
       (new ScaleListener()).scaleIt(3f,currentTapLocation.x,currentTapLocation.y); 
       zoomCenter = currentTapLocation; 
       zoomedInLastTime = true; 
      }else { 
       (new ScaleListener()).scaleIt(.33f, zoomCenter.x, zoomCenter.y); 
       zoomedInLastTime = false; 
      } 
      return true; 
     } 

     @Override 
     public boolean onDoubleTapEvent(MotionEvent motionEvent) { 
      return false; 
     } 
    }); 
    matrix.setTranslate(1f, 1f); 
    floatArray = new float[9]; 
    setImageMatrix(matrix); 

    setOnTouchListener(new DoubleTapPinchZoomListener()); 
} 

@Override 
public void setImageBitmap(Bitmap bm) { 
    super.setImageBitmap(bm); 
    if(bm != null) { 
     if (Build.VERSION.SDK_INT > 17){ 
      imageWidth = bm.getWidth(); 
      imageHeight = bm.getHeight(); 
     } else { 
      imageWidth = 2*bm.getWidth(); 
      imageHeight = 2*bm.getHeight(); 
     } 
    } 
} 

public void setMaxZoom(float x) 
{ 
    maxScale = x; 
} 

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
    @Override 
    public boolean onScaleBegin(ScaleGestureDetector detector) { 
     mode = ZOOM; 
     return true; 
    } 

    @Override 
    public boolean onScale(ScaleGestureDetector detector) { 
     float mScaleFactor = detector.getScaleFactor(); 
     scaleIt(mScaleFactor, detector.getFocusX(), detector.getFocusY()); 
     return true; 
    } 

    public void scaleIt(float mScaleFactor, float focusx, float focusy){ 
     float origScale = initialScale; 
     initialScale *= mScaleFactor; 
     if (initialScale > maxScale) { 
      initialScale = maxScale; 
      mScaleFactor = maxScale/origScale; 
     } else if (initialScale < minScale) { 
      initialScale = minScale; 
      mScaleFactor = minScale/origScale; 
     } 
     right = imageViewWidth * initialScale - imageViewWidth - (2 * unusedWidth * initialScale); 
     bottom = imageViewHeight * initialScale - imageViewHeight - (2 * unusedHeight * initialScale); 
     if (origWidth * initialScale <= imageViewWidth || origHeight * initialScale <= imageViewHeight) { 
      matrix.postScale(mScaleFactor, mScaleFactor, imageViewWidth/2, imageViewHeight/2); 
      if (mScaleFactor < 1) { 
       matrix.getValues(floatArray); 
       float x = floatArray[Matrix.MTRANS_X]; 
       float y = floatArray[Matrix.MTRANS_Y]; 
       if (mScaleFactor < 1) { 
        if (Math.round(origWidth * initialScale) < imageViewWidth) { 
         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, focusx, focusy); 
      matrix.getValues(floatArray); 
      float x = floatArray[Matrix.MTRANS_X]; 
      float y = floatArray[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); 
      } 
     } 
    } 
} 

@Override 
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec){ 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 

    imageViewWidth = MeasureSpec.getSize(widthMeasureSpec); 
    imageViewHeight = MeasureSpec.getSize(heightMeasureSpec); 

    /*RectF drawableRect = new RectF(0, 0, imageWidth, imageHeight); 
    RectF viewRect = new RectF(0, 0, imageViewWidth, imageViewHeight); 

    //draw the image in the view 
    matrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);*/ 

    //Fit to screen. 
    float scale; 
    float scaleX = (float) imageViewWidth/(float)(imageWidth); 
    float scaleY = (float) imageViewHeight/(float)(imageHeight); 
    scale = Math.min(scaleX, scaleY); 
    matrix.setScale(scale, scale); 
    setImageMatrix(matrix); 
    initialScale = 1f; 

    // Center the image 
    unusedHeight = (float) imageViewHeight - (scale * (float) imageHeight) ; 
    unusedWidth = (float) imageViewWidth - (scale * (float) imageWidth); 
    unusedHeight /= (float)2; 
    unusedWidth /= (float)2; 

    matrix.postTranslate(unusedWidth, unusedHeight); 

    origWidth = imageViewWidth - 2 * unusedWidth; 
    origHeight = imageViewHeight - 2 * unusedHeight; 
    right = imageViewWidth * initialScale - imageViewWidth - (2 * unusedWidth * initialScale); 
    bottom = imageViewHeight * initialScale - imageViewHeight - (2 * unusedHeight * initialScale); 
    setImageMatrix(matrix); 
} 

class DoubleTapPinchZoomListener implements OnTouchListener { 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     mScaleDetector.onTouchEvent(event); 

     mDetector.onTouchEvent(event); 

     matrix.getValues(floatArray); 
     float x = floatArray[Matrix.MTRANS_X]; 
     float y = floatArray[Matrix.MTRANS_Y]; 
     PointF curr = new PointF(event.getX(), event.getY()); 

     switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       last.set(event.getX(), event.getY()); 
       start.set(last); 
       mode = DRAG; 
       break; 
      case MotionEvent.ACTION_MOVE: 
       if (mode == DRAG) { 
        float deltaX = curr.x - last.x; 
        float deltaY = curr.y - last.y; 
        float scaleWidth = Math.round(origWidth * initialScale); 
        float scaleHeight = Math.round(origHeight * initialScale); 
        if (scaleWidth < imageViewWidth) { 
         deltaX = 0; 
         if (y + deltaY > 0) 
          deltaY = -y; 
         else if (y + deltaY < -bottom) 
          deltaY = -(y + bottom); 
        } else if (scaleHeight < imageViewHeight) { 
         deltaY = 0; 
         if (x + deltaX > 0) 
          deltaX = -x; 
         else if (x + deltaX < -right) 
          deltaX = -(x + right); 
        } else { 
         if (x + deltaX > 0) 
          deltaX = -x; 
         else if (x + deltaX < -right) 
          deltaX = -(x + right); 

         if (y + deltaY > 0) 
          deltaY = -y; 
         else if (y + deltaY < -bottom) 
          deltaY = -(y + bottom); 
        } 
        matrix.postTranslate(deltaX, deltaY); 
        last.set(curr.x, curr.y); 
       } 
       break; 

      case MotionEvent.ACTION_POINTER_UP: 
       mode = NONE; 
       break; 
     } 
     setImageMatrix(matrix); 
     invalidate(); 
     return true; 
    } 
} 
} 
+0

你找到答案 –

+0

@TerrilThomas是的,我做到了。我把我的圖像文件放在res> drawable中,而不是res> drawable-nodpi。因此,android並不知道不會自動縮放它,所以雖然我所有的計算都是正確的,但是它又一次變大了,這讓事情變得糟糕。我會創建一個答案,並在接下來的一週左右接受它。 –

回答

1

原來這個問題與MATRIX縮放無關,儘管這對我來說仍然有點神祕。問題是'automagic'重新縮放。我將我的圖片放在'可繪製'文件夾中,Android會自動縮放爲'最適合屏幕尺寸'。有關更多信息,請參見這裏:

http://developer.android.com/guide/practices/screens_support.html#support

的解決方案是把圖像中繪製-nodpi。這告訴Android不要根據屏幕大小進行重新調整,因此,手動操作縮放並不會與Android自己的縮放比例相沖突。