在SurfaceView中缩放和拖动function

我正在尝试创build一个可以缩放和拖动的SurfaceView。 它实现了直接绘制到canvas中的HTTP图像stream

我试过下面的代码,它有点工作…但它给我在边界的问题。 不知道为什么。 任何帮助?

完整的stream:

完整的流图像

缩放图像:

放大的图像

在第二个图像中,您可以看到多条不需要在那里的绿线。

这是处理这个stream的类:

import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.Display; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.SurfaceView; import android.view.WindowManager; /** * Created by fil on 07/12/15. */ public class ZoomSurfaceView extends SurfaceView { //These two constants specify the minimum and maximum zoom private static float MIN_ZOOM = 1f; private static float MAX_ZOOM = 5f; private float scaleFactor = 1.f; private ScaleGestureDetector detector; //These constants specify the mode that we're in private static int NONE = 0; private static int DRAG = 1; private static int ZOOM = 2; private boolean dragged = false; private float displayWidth; private float displayHeight; private int mode; //These two variables keep track of the X and Y coordinate of the finger when it first //touches the screen private float startX = 0f; private float startY = 0f; //These two variables keep track of the amount we need to translate the canvas along the X //and the Y coordinate private float translateX = 0f; private float translateY = 0f; //These two variables keep track of the amount we translated the X and Y coordinates, the last time we //panned. private float previousTranslateX = 0f; private float previousTranslateY = 0f; private final Paint p = new Paint(); private void init(Context context){ detector = new ScaleGestureDetector(getContext(), new ScaleListener()); WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); displayWidth = display.getWidth(); displayHeight = display.getHeight(); } public ZoomSurfaceView(Context context) { super(context); init(context); } public ZoomSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public ZoomSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } public ZoomSurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context); } public void resetZoom() { } public void drawBitmap(Canvas canvas, Bitmap b, Rect rect){ canvas.save(); //If translateX times -1 is lesser than zero, letfs set it to zero. This takes care of the left bound if((translateX * -1) > (scaleFactor - 1) * displayWidth) { translateX = (1 - scaleFactor) * displayWidth; } if(translateY * -1 > (scaleFactor - 1) * displayHeight) { translateY = (1 - scaleFactor) * displayHeight; } //We need to divide by the scale factor here, otherwise we end up with excessive panning based on our zoom level //because the translation amount also gets scaled according to how much we've zoomed into the canvas. canvas.translate(translateX / scaleFactor, translateY / scaleFactor); //We're going to scale the X and Y coordinates by the same amount canvas.scale(scaleFactor, scaleFactor); canvas.drawBitmap(b, null, rect, p); /* The rest of your canvas-drawing code */ canvas.restore(); } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { scaleFactor *= detector.getScaleFactor(); scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM)); return true; } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mode = DRAG; //We assign the current X and Y coordinate of the finger to startX and startY minus the previously translated //amount for each coordinates This works even when we are translating the first time because the initial //values for these two variables is zero. startX = event.getX() - previousTranslateX; startY = event.getY() - previousTranslateY; break; case MotionEvent.ACTION_MOVE: translateX = event.getX() - startX; translateY = event.getY() - startY; //We cannot use startX and startY directly because we have adjusted their values using the previous translation values. //This is why we need to add those values to startX and startY so that we can get the actual coordinates of the finger. double distance = Math.sqrt(Math.pow(event.getX() - (startX + previousTranslateX), 2) + Math.pow(event.getY() - (startY + previousTranslateY), 2)); if(distance > 0) { dragged = true; distance *= scaleFactor; } break; case MotionEvent.ACTION_POINTER_DOWN: break; case MotionEvent.ACTION_UP: mode = NONE; dragged = false; //All fingers went up, so letfs save the value of translateX and translateY into previousTranslateX and //previousTranslate previousTranslateX = translateX; previousTranslateY = translateY; break; case MotionEvent.ACTION_POINTER_UP: mode = DRAG; //This is not strictly necessary; we save the value of translateX and translateY into previousTranslateX //and previousTranslateY when the second finger goes up previousTranslateX = translateX; previousTranslateY = translateY; break; } detector.onTouchEvent(event); //We redraw the canvas only in the following cases: // // o The mode is ZOOM // OR // o The mode is DRAG and the scale factor is not equal to 1 (meaning we have zoomed) and dragged is // set to true (meaning the finger has actually moved) if ((mode == DRAG && scaleFactor != 1f && dragged) || mode == ZOOM) { invalidate(); } return true; } } 

将帧添加到表面的代码如下所示:

 if (!b.isRecycled()){ try { Rect rect = new Rect(0, 0, frame.getWidth(), frame.getHeight()); Canvas canvas = frame.getHolder().lockCanvas(); synchronized (frame.getHolder()) { if (!b.isRecycled()) { frame.drawBitmap(canvas, b, rect); b.recycle(); } } frame.getHolder().unlockCanvasAndPost(canvas); } catch (java.lang.RuntimeException exc){ Dbg.d("ERROR", exc); } lastBitmap = b; } 

Solutions Collecting From Web of "在SurfaceView中缩放和拖动function"

您发布的代码不完整,因此难以说明问题所在。 我没有把你的代码放到一个快速演示项目中,没有看到任何边界问题。

只要看截图:任何你的图像数据以某种方式包装的机会? 第二张截图看起来像是在图像顶部绘制底部边框。 再次强硬的说没有可重复的代码。

在重绘位图之前,可能会尝试重新绘制背景

 canvas.drawRect(rect, backgroundPaint); frame.drawBitmap(canvas, b, rect);