Android之實現手勢縮放的ImageView

來源:互聯網
上載者:User

方法一:

將以下代碼寫到MulitPointTouchListener.java中,然後對你相應的圖片進行OnTouchListener。
例如:imageView.setOnTouchListener(new MulitPointTouchListener ());

在xml中要將ImageView的縮放格式改成Matrix

例如:android:scaleType="matrix"

這樣就可以實現圖片的縮放了

 

下面是MulitPointTouchListener.java代碼:

public class MulitPointTouchListener implements OnTouchListener {           private static final String TAG = "Touch";           // These matrices will be used to move and zoom image           Matrix matrix = new Matrix();           Matrix savedMatrix = 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 start = new PointF();           PointF mid = new PointF();           float oldDist = 1f;             @Override          public boolean onTouch(View v, MotionEvent event) {                     ImageView view = (ImageView) v;                   // Log.e("view_width",                   // view.getImageMatrix()..toString()+"*"+v.getWidth());                   // Dump touch event to log                   dumpEvent(event);                     // Handle touch events here...                   switch (event.getAction() & MotionEvent.ACTION_MASK) {                   case MotionEvent.ACTION_DOWN:                             matrix.set(view.getImageMatrix());                           savedMatrix.set(matrix);                           start.set(event.getX(), event.getY());                           //Log.d(TAG, "mode=DRAG");                           mode = DRAG;                                                       //Log.d(TAG, "mode=NONE");                           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");                           }                           break;                   case MotionEvent.ACTION_UP:                   case MotionEvent.ACTION_POINTER_UP:                           mode = NONE;                           //Log.e("view.getWidth", view.getWidth() + "");                           //Log.e("view.getHeight", view.getHeight() + "");                             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) {                                   float newDist = spacing(event);                                   //Log.d(TAG, "newDist=" + newDist);                                   if (newDist > 10f) {                                           matrix.set(savedMatrix);                                           float scale = newDist / oldDist;                                           matrix.postScale(scale, scale, mid.x, mid.y);                                   }                           }                           break;                   }                     view.setImageMatrix(matrix);                   return true; // indicate event was handled           }             private void dumpEvent(MotionEvent 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());           }                       private float spacing(MotionEvent event) {                   float x = event.getX(0) - event.getX(1);                   float y = event.getY(0) - event.getY(1);                   return FloatMath.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);           }   }  

方法二:自訂一個ImageView,例如TouchImageView:

import android.content.Context;import android.graphics.Matrix;import android.graphics.PointF;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.ScaleGestureDetector;import android.view.View;import android.widget.ImageView;public class TouchImageView extends ImageView {    Matrix 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 = 3f;    float[] m;    int viewWidth, viewHeight;    static final int CLICK = 3;    float saveScale = 1f;    protected float origWidth, origHeight;    int oldMeasuredWidth, oldMeasuredHeight;    ScaleGestureDetector mScaleDetector;    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;        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());        matrix = new Matrix();        m = new float[9];        setImageMatrix(matrix);        setScaleType(ScaleType.MATRIX);        setOnTouchListener(new OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                mScaleDetector.onTouchEvent(event);                PointF curr = new PointF(event.getX(), event.getY());                switch (event.getAction()) {                    case MotionEvent.ACTION_DOWN:                    last.set(curr);                        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 fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);                            float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale);                            matrix.postTranslate(fixTransX, fixTransY);                            fixTrans();                            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 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();            float origScale = saveScale;            saveScale *= mScaleFactor;            if (saveScale > maxScale) {                saveScale = maxScale;                mScaleFactor = maxScale / origScale;            } else if (saveScale < minScale) {                saveScale = minScale;                mScaleFactor = minScale / origScale;            }            if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight)                matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);            else                matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());            fixTrans();            return true;        }    }    void fixTrans() {        matrix.getValues(m);        float transX = m[Matrix.MTRANS_X];        float transY = m[Matrix.MTRANS_Y];                float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);        float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);        if (fixTransX != 0 || fixTransY != 0)            matrix.postTranslate(fixTransX, fixTransY);    }    float getFixTrans(float trans, float viewSize, float contentSize) {        float minTrans, maxTrans;        if (contentSize <= viewSize) {            minTrans = 0;            maxTrans = viewSize - contentSize;        } else {            minTrans = viewSize - contentSize;            maxTrans = 0;        }        if (trans < minTrans)            return -trans + minTrans;        if (trans > maxTrans)            return -trans + maxTrans;        return 0;    }        float getFixDragTrans(float delta, float viewSize, float contentSize) {        if (contentSize <= viewSize) {            return 0;        }        return delta;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        viewWidth = MeasureSpec.getSize(widthMeasureSpec);        viewHeight = MeasureSpec.getSize(heightMeasureSpec);                //        // Rescales image on rotation        //        if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight                || viewWidth == 0 || viewHeight == 0)            return;        oldMeasuredHeight = viewHeight;        oldMeasuredWidth = viewWidth;        if (saveScale == 1) {            //Fit to screen.            float scale;            Drawable drawable = getDrawable();            if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0)                return;            int bmWidth = drawable.getIntrinsicWidth();            int bmHeight = drawable.getIntrinsicHeight();                        Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);            float scaleX = (float) viewWidth / (float) bmWidth;            float scaleY = (float) viewHeight / (float) bmHeight;            scale = Math.min(scaleX, scaleY);            matrix.setScale(scale, scale);            // Center the image            float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight);            float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth);            redundantYSpace /= (float) 2;            redundantXSpace /= (float) 2;            matrix.postTranslate(redundantXSpace, redundantYSpace);            origWidth = viewWidth - 2 * redundantXSpace;            origHeight = viewHeight - 2 * redundantYSpace;            setImageMatrix(matrix);        }        fixTrans();    }}

然後在我們的Activity中就可以直接使用了:

public class TouchImageViewActivity extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        TouchImageView img = (TouchImageView) findViewById(R.id.snoop);        img.setImageResource(R.drawable.snoopy);        img.setMaxZoom(4f);    }}

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.