使用Android构build的手势监听器和缩放监听器来实现捏放大和拖动

我正在尝试使用Android的手势监听器和缩放监听器来实现捏放大和拖动。 问题是,当我执行捏缩放,图像(我想缩放)反弹到一个特定的位置。 缩放位置也不居中。 以下代码演示了我试图实现的内容。 任何想法为什么图像跳跃(以及如何纠正)?

public class CustomView extends View { Bitmap image; int screenHeight; int screenWidth; Paint paint; GestureDetector gestures; ScaleGestureDetector scaleGesture; float scale = 1.0f; float horizontalOffset, verticalOffset; int NORMAL = 0; int ZOOM = 1; int DRAG = 2; boolean isScaling = false; float touchX, touchY; int mode = NORMAL; public CustomView(Context context) { super(context); //initializing variables image = BitmapFactory.decodeResource(getResources(), R.drawable.image_name); //This is a full screen view screenWidth = getResources().getDisplayMetrics().widthPixels; screenHeight = getResources().getDisplayMetrics().heightPixels; paint = new Paint(); paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); paint.setColor(Color.WHITE); scaleGesture = new ScaleGestureDetector(getContext(), new ScaleListener()); gestures = new GestureDetector(getContext(), new GestureListener()); mode = NORMAL; initialize(); } //Best fit image display on canvas private void initialize() { float imgPartRatio = image.getWidth() / (float) image.getHeight(); float screenRatio = (float) screenWidth / (float) screenHeight; if (screenRatio > imgPartRatio) { scale = ((float) screenHeight) / (float) (image.getHeight()); // fit height horizontalOffset = ((float) screenWidth - scale * (float) (image.getWidth())) / 2.0f; verticalOffset = 0; } else { scale = ((float) screenWidth) / (float) (image.getWidth()); // fit width horizontalOffset = 0; verticalOffset = ((float) screenHeight - scale * (float) (image.getHeight())) / 2.0f; } invalidate(); } @Override protected void onDraw(Canvas canvas) { canvas.save(); canvas.drawColor(0, Mode.CLEAR); canvas.drawColor(Color.WHITE); if(mode == DRAG || mode == NORMAL) { //This works perfectly as expected canvas.translate(horizontalOffset, verticalOffset); canvas.scale(scale, scale); canvas.drawBitmap(image, getMatrix(), paint); } else if (mode == ZOOM) { //PROBLEM AREA - when applying pinch zoom, //the image jumps to a position abruptly canvas.scale(scale, scale, touchX, touchY); canvas.drawBitmap(image, getMatrix(), paint); } canvas.restore(); } public class ScaleListener implements OnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { float scaleFactorNew = detector.getScaleFactor(); if (detector.isInProgress()) { touchX = detector.getFocusX(); touchY = detector.getFocusY(); scale *= scaleFactorNew; invalidate(0, 0, screenWidth, screenHeight); } return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { isScaling = true; mode=ZOOM; return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { mode = NORMAL; isScaling = false; } } public class GestureListener implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener { @Override public boolean onDown(MotionEvent e) { isScaling = false; return true; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (!isScaling) { mode = DRAG; isScaling = false; horizontalOffset -= distanceX; verticalOffset -= distanceY; invalidate(0, 0, screenWidth, screenHeight); } else { mode = ZOOM; isScaling = true; } return true; } } @Override public boolean onTouchEvent(MotionEvent event) { scaleGesture.onTouchEvent(event); gestures.onTouchEvent(event); return true; } } 

提前致谢。

Solutions Collecting From Web of "使用Android构build的手势监听器和缩放监听器来实现捏放大和拖动"

我已经实现了这种行为,我用matrix来处理所有的缩放和滚动(在我的情况下,旋转)。 它使整齐的代码和作品像发条。

将matrix存储为类成员:

 Matrix drawMatrix; 

编辑:存储旧的焦点,用于在缩放过程中获得焦点位移。

 float lastFocusX; float lastFocusY; 

编辑 :在onScaleBegin中设置lastFocusvariables

 @Override public boolean onScaleBegin(ScaleGestureDetector detector) { lastFocusX = detector.getFocusX(); lastFocusY = detector.getFocusY(); return true; } 

replace您的onScale:

 @Override public boolean onScale(ScaleGestureDetector detector) { Matrix transformationMatrix = new Matrix(); float focusX = detector.getFocusX(); float focusY = detector.getFocusY(); //Zoom focus is where the fingers are centered, transformationMatrix.postTranslate(-focusX, -focusY); transformationMatrix.postScale(detector.getScaleFactor(), detector.getScaleFactor()); /* Adding focus shift to allow for scrolling with two pointers down. Remove it to skip this functionality. This could be done in fewer lines, but for clarity I do it this way here */ //Edited after comment by chochim float focusShiftX = focusX - lastFocusX; float focusShiftY = focusY - lastFocusY; transformationMatrix.postTranslate(focusX + focusShiftX, focusY + focusShiftY); drawMatrix.postConcat(transformationMatrix); lastFocusX = focusX; lastFocusY = focusY; invalidate(); return true; } 

同样在onScroll中:

 @Override public boolean onScroll(MotionEvent downEvent, MotionEvent currentEvent, float distanceX, float distanceY) { drawMatrix.postTranslate(-distanceX, -distanceY); invalidate(); return true; } 

在onDraw; 用drawMatrix绘制:

 canvas.drawBitmap(image, drawMatrix, paint); 

快乐的编码!