2015-10-20 129 views
1

我跟着guideline I found in the Android Developer Blog調整大小的ImageView與捏

但問題是,這只是移動和圖像視圖邊界內變焦。我想要的是用兩個手指手勢調整圖像視圖的大小。它應該變得更大或更小根據捏。我已經一直在調整整天的谷歌搜索,並無法弄清楚。所有的教程只指出我在ImageView中縮放而不是調整大小。 以下是我的自定義圖像視圖代碼產生的博客。

public class InteractableImageView extends ImageView implements View.OnTouchListener { 

    private static final int INVALID_POINTER_ID = -1; 
    private ScaleGestureDetector mScaleDetector; 
    private float mScaleFactor = 1.f; 
    private int mActivePointerId = INVALID_POINTER_ID; 
    private float mPosX; 
    private float mPosY; 

    private float mLastTouchX; 
    private float mLastTouchY; 

    public InteractableImageView(Context context) { 
    this(context, null, 0); 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
    } 

    public InteractableImageView(Context context, AttributeSet attrs) { 
    this(context, attrs, 0); 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
    } 

    public InteractableImageView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
    } 

    public boolean onTouchEvent(MotionEvent ev) { 
    // Let the ScaleGestureDetector inspect all events. 
    mScaleDetector.onTouchEvent(ev); 

    final int action = ev.getAction(); 
    switch (action & MotionEvent.ACTION_MASK) { 
     case MotionEvent.ACTION_DOWN: { 
     final float x = ev.getX(); 
     final float y = ev.getY(); 

     mLastTouchX = x; 
     mLastTouchY = y; 
     mActivePointerId = ev.getPointerId(0); 
     break; 
     } 

     case MotionEvent.ACTION_MOVE: { 
     final int pointerIndex = ev.findPointerIndex(mActivePointerId); 
     final float x = ev.getX(pointerIndex); 
     final float y = ev.getY(pointerIndex); 

     // Only move if the ScaleGestureDetector isn't processing a gesture. 
     if (!mScaleDetector.isInProgress()) { 
      final float dx = x - mLastTouchX; 
      final float dy = y - mLastTouchY; 

      mPosX += dx; 
      mPosY += dy; 

      invalidate(); 
     } 

     mLastTouchX = x; 
     mLastTouchY = y; 

     break; 
     } 

     case MotionEvent.ACTION_UP: { 
     mActivePointerId = INVALID_POINTER_ID; 
     break; 
     } 

     case MotionEvent.ACTION_CANCEL: { 
     mActivePointerId = INVALID_POINTER_ID; 
     break; 
     } 

     case MotionEvent.ACTION_POINTER_UP: { 
     final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
      >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
     final int pointerId = ev.getPointerId(pointerIndex); 
     if (pointerId == mActivePointerId) { 
      // This was our active pointer going up. Choose a new 
      // active pointer and adjust accordingly. 
      final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
      mLastTouchX = ev.getX(newPointerIndex); 
      mLastTouchY = ev.getY(newPointerIndex); 
      mActivePointerId = ev.getPointerId(newPointerIndex); 
     } 
     break; 
     } 
    } 

    return true; 
    } 

    @Override public void onDraw(Canvas canvas) { 
    canvas.save(); 
    canvas.translate(mPosX, mPosY); 
    canvas.scale(mScaleFactor, mScaleFactor); 
    super.onDraw(canvas); 
    canvas.restore(); 
    } 

    @Override public boolean onTouch(View v, MotionEvent event) { 
    return false; 
    } 

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
    @Override public boolean onScale(ScaleGestureDetector detector) { 
     mScaleFactor *= detector.getScaleFactor(); 

     // Don't let the object get too small or too large. 
     mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f)); 

     invalidate(); 
     return true; 
    } 
    } 
} 

回答

1

試試這個。

在你的XML,

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/container" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
    <com.yourpackagename.CustomImageView 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:scaleType="matrix" 
     android:src="@mipmap/ic_launcher"/> 
</RelativeLayout> 

的CustomImageView,

import android.content.Context; 
import android.graphics.Matrix; 
import android.graphics.PointF; 
import android.graphics.drawable.Drawable; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.view.View; 
import android.widget.ImageView; 

/** 
* Created by yeminhtut on 10/21/15. 
*/ 
public class CustomImageView extends ImageView implements View.OnTouchListener { 
    Matrix matrix = new Matrix(); 
    Matrix savedMatrix = new Matrix(); 
    Matrix savedMatrix2 = 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; 
    float[] lastEvent; 
    float d; 

    // Remember some things for zooming 
    PointF start = new PointF(); 
    PointF mid = new PointF(); 
    float oldDist = 1f; 
    public CustomImageView(Context context) { 
     super(context); 
    } 

    public CustomImageView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     this.setOnTouchListener(this); 
    } 

    public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 


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

     // 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()); 
       mode = DRAG; 
       break; 

      case MotionEvent.ACTION_POINTER_DOWN: 
       oldDist = spacing(event); 
       if (oldDist > 10f) { 
        savedMatrix.set(matrix); 
        midPoint(mid, event); 
        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: //first finger lifted 
      case MotionEvent.ACTION_POINTER_UP: //second finger lifted 
       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); 
        matrix.set(savedMatrix); 
        if (newDist > 10f) { 
         scale = newDist/oldDist; 
         matrix.postScale(scale, scale, mid.x, mid.y); 
        } 
        if (lastEvent != null) { 
         float newRot = rotation(event); 
         float r = newRot - d; 
         matrix.postRotate(r, view.getMeasuredWidth()/2, 
           view.getMeasuredHeight()/2); 
        } 
       } 
       break; 

     } 
     // Perform the transformation 
     fixing(); 
     view.setImageMatrix(savedMatrix2); 

     return true; // indicate event was handled 

    } 
    public void fixing() 
     { 

     float[] value = new float[9]; 
     matrix.getValues(value); 

     float[] savedValue = new float[9]; 
     savedMatrix2.getValues(savedValue); 

     int width = this.getWidth(); 
     int height = this.getHeight(); 

     Drawable d = this.getDrawable(); 
     if (d == null) return; 
     int imageWidth = d.getIntrinsicWidth(); 
     int imageHeight = d.getIntrinsicHeight(); 
     int scaleWidth = (int) (imageWidth * value[0]); 
     int scaleHeight = (int) (imageHeight * value[4]); 

// don't let the image go outside 
     if (value[2] > width-1) 
      value[2] = width-10; 
     else if (value[5] > height - 1) 
      value[5] = height - 10; 
     else if (value[2] < -(scaleWidth-1)) 
      value[2] = -(scaleWidth-10); 
     else if (value[5] < -(scaleHeight-1)) 
      value[5] = -(scaleHeight-10); 

     matrix.setValues(value); 
     savedMatrix2.set(matrix); 
    } 
    private float rotation(MotionEvent 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); 

     return (float) Math.toDegrees(radians); 
    } 

    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); 

    } 
} 

希望這有助於:)。 快樂編碼。

-1

這可以用一個lib可以輕鬆實現:PhotoView

所有你需要做的是:

new PhotoViewAttacher(mImageView); 

,你會對你的ImageView實現手勢檢測