2012-11-07 62 views
1

编辑:或者,如果任何人有其他方法实施捏放大,这将是非常有益的。捏放大的图像,但ImageView不会改变大小

在我的项目中,我有几个ImageViews在一个页面上,每个需要能够单独放大。我迄今已使用此代码CONTROLL变焦

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 = 0f; 
float maxScale = 2f; 
float[] m; 

float redundantXSpace, redundantYSpace; 

float width, height; 
static final int CLICK = 3; 
float saveScale = 1f; 
float right, bottom, origWidth, origHeight, bmWidth, bmHeight; 

ScaleGestureDetector mScaleDetector; 

Context context; 

TouchImageView thisImageView = this; 


public TouchImageView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    super.setClickable(true); 
    this.context = context; 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
    matrix.setTranslate(1f, 1f); 
    m = new float[9]; 
    setImageMatrix(matrix); 
    setScaleType(ScaleType.MATRIX); 

    setOnTouchListener(new OnTouchListener() { 
     public boolean onTouch(View v, MotionEvent event) { 
      mScaleDetector.onTouchEvent(event); 

      matrix.getValues(m); 
      float x = m[Matrix.MTRANS_X]; 
      float y = m[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 * saveScale); 
        float scaleHeight = Math.round(origHeight * saveScale); 
        if (scaleWidth < width) { 
         deltaX = 0; 
         if (y + deltaY > 0) 
          deltaY = -y; 
         else if (y + deltaY < -bottom) 
          deltaY = -(y + bottom); 
        } else if (scaleHeight < height) { 
         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_UP: 
       mode = NONE; 
       int xDiff = (int) Math.abs(curr.x - start.x); 
       int yDiff = (int) Math.abs(curr.y - start.y); 
       if (xDiff < CLICK && yDiff < CLICK) 
        performClick(); 
       break; 

      case MotionEvent.ACTION_POINTER_UP: 
       mode = NONE; 
       break; 
      } 
      setImageMatrix(matrix); 
      invalidate(); 
      return true; // indicate event was handled 
     } 

    }); 
} 

public void setImageDrawable(Drawable dr) { 
    super.setImageDrawable(dr); 
    bmWidth = dr.getIntrinsicWidth(); 
    bmHeight = dr.getIntrinsicHeight(); 
} 

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 = (float)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05); 
     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, detector.getFocusX(), detector.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); 
      } 

     } 
     return true; 

    } 
} 

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

    System.out.println(widthMeasureSpec + " " + heightMeasureSpec); 

    int w = (int) bmWidth; 
    int h = (int) bmHeight; 
    width = resolveSize(w, widthMeasureSpec); 
    height = resolveSize(h, heightMeasureSpec); 

    //Fit to screen. 
    float scale; 
    float scaleX = (float)width/(float)bmWidth; 
    float scaleY = (float)height/(float)bmHeight; 
    scale = Math.min(scaleX, scaleY); 
    matrix.setScale(scale, scale); 
    setImageMatrix(matrix); 
    saveScale = 1f; 

    // Center the image 
    redundantYSpace = (float)height - (scale * (float)bmHeight) ; 
    redundantXSpace = (float)width - (scale * (float)bmWidth); 
    redundantYSpace /= (float)2; 
    redundantXSpace /= (float)2; 

    matrix.postTranslate(redundantXSpace, redundantYSpace); 

    origWidth = width - 2 * redundantXSpace; 
    origHeight = height - 2 * redundantYSpace; 
    right = width * saveScale - width - (2 * redundantXSpace * saveScale); 
    bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); 
    setImageMatrix(matrix); 
} 

}

其中一期工程,但是当我捏在ImageView的变焦只能在图像内的增长和在尺寸缩小。实际的ImageView保持相同的大小,这意味着它经常离开ImageView的边缘并变得不可见。使用双指缩放以及使用的

到目前为止,我已经尝试了许多不同的方法:

android:adjustViewBounds="true" 
    android:scaleType="centerInside" 

试图迫使该ImageView的改变大小。

任何帮助将不胜感激。

回答

2

试试这个

public class Touch extends Activity implements OnTouchListener, OnClickListener { 
    private static final String TAG = "Touch"; 
    // These matrices will be used to move and zoom image 
    Matrix matrix = new Matrix(); 
    Matrix savedMatrix = new Matrix(); 
    String extStorageDirectory; 

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

    int r = 0; 

    // Remember some things for zooming 
    PointF start = new PointF(); 
    PointF mid = new PointF(); 
    float oldDist = 1f; 
    Bitmap bm; 
    int fCount = 0; 

    File _photoFile; 
    Uri _fileUri; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     ImageView view = (ImageView) findViewById(R.id.imageView); 
     view.setOnTouchListener(this); 


     showImage(); 

     // ... 
     // Work around a Cupcake bug 
     matrix.setTranslate(1f, 1f); 
     view.setImageMatrix(matrix); 



    float[] lastEvent = null; 
    float d = 0f; 
    float newRot = 0f; 

    @Override 
    public boolean onTouch(View v, MotionEvent rawEvent) { 
     WrapMotionEvent event = WrapMotionEvent.wrap(rawEvent); 
     // ... 
     // Dump touch event to log 
     dumpEvent(event); 
     ImageView view = (ImageView) v; 

     // Dump touch event to log 
     dumpEvent(event); 
     // 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"); 
       lastEvent = new float[4]; 
       lastEvent[0] = event.getX(0); 
       lastEvent[1] = event.getX(1); 
       lastEvent[2] = event.getY(0); 
       lastEvent[3] = event.getY(1); 
       d = rotation(event); 
      } 

      break; 

     case MotionEvent.ACTION_UP: 

      mode = NONE; 
      Log.d(TAG, "mode=NONE"); 
      savedMatrix.set(matrix); 
      // matrix.postRotate(90); 

      break; 

     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 && event.getPointerCount() == 2) { 
       float newDist = spacing(event); 
       Log.d(TAG, "Count=" + event.getPointerCount()); 
       Log.d(TAG, "newDist=" + newDist); 
       matrix.set(savedMatrix); 
       if (newDist > 10f) { 
        matrix.set(savedMatrix); 
        float scale = newDist/oldDist; 
        matrix.postScale(scale, scale, mid.x, mid.y); 

       } 
       if (lastEvent != null) { 
        newRot = rotation(event); 
        Log.d("Dgereeee", "newRot=" + (newRot)); 
        float r = newRot - d; 
        matrix.postRotate(r, view.getMeasuredWidth()/2, 
          view.getMeasuredHeight()/2); 
       } 
      } 
      break; 

     } 

     view.setImageMatrix(matrix); 
     return true; // indicate event was handled 
    } 

    /** Show an event in the LogCat view, for debugging */ 
    private void dumpEvent(WrapMotionEvent event) { 
     // ... 
     String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE", 
       "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" }; 
     StringBuilder sb = new StringBuilder(); 
     int action = event.getAction(); 
     int actionCode = action & MotionEvent.ACTION_MASK; 
     sb.append("event ACTION_").append(names[actionCode]); 
     if (actionCode == MotionEvent.ACTION_POINTER_DOWN 
       || actionCode == MotionEvent.ACTION_POINTER_UP) { 
      sb.append("(pid ").append(
        action >> MotionEvent.ACTION_POINTER_ID_SHIFT); 
      sb.append(")"); 
     } 
     sb.append("["); 
     for (int i = 0; i < event.getPointerCount(); i++) { 
      sb.append("#").append(i); 
      sb.append("(pid ").append(event.getPointerId(i)); 
      sb.append(")=").append((int) event.getX(i)); 
      sb.append(",").append((int) event.getY(i)); 
      if (i + 1 < event.getPointerCount()) 
       sb.append(";"); 
     } 
     sb.append("]"); 
     Log.d(TAG, sb.toString()); 
    } 

    /** Determine the space between the first two fingers */ 
    private float spacing(WrapMotionEvent event) { 
     // ... 
     float x = event.getX(0) - event.getX(1); 
     float y = event.getY(0) - event.getY(1); 
     return FloatMath.sqrt(x * x + y * y); 
    } 

    /** Determine the degree between the first two fingers */ 
    private float rotation(WrapMotionEvent event) { 
     double delta_x = (event.getX(0) - event.getX(1)); 
     double delta_y = (event.getY(0) - event.getY(1)); 
     double radians = Math.atan2(delta_y, delta_x); 
     Log.d("Rotation ~~~~~~~~~~~~~~~~~", delta_x + " ## " + delta_y + " ## " 
       + radians + " ## " + Math.toDegrees(radians)); 
     return (float) Math.toDegrees(radians); 
    } 

    /** Calculate the mid point of the first two fingers */ 
    private void midPoint(PointF point, WrapMotionEvent event) { 
     // ... 
     float x = event.getX(0) + event.getX(1); 
     float y = event.getY(0) + event.getY(1); 
     point.set(x/2, y/2); 
    } 


} 

,并在你的XML应用规模类型矩阵

android:scaleType="matrix" 
+0

我不是完全肯定我将如何能够工作到我的代码这一点。 – Marche101

+0

@ Marche101检查我编辑过的ans – Numair

+0

但是oldDist,savedMatrix和lastEvent到底是什么?和间距()? – Marche101