转自:http://blog.csdn.net/way_ping_li/article/details/8477786
方法一:
将以下代码写到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);
- }
- }