2015-12-11 16 views
21

Tôi đang cố tạo SurfaceView có thể được thu phóng và kéo. Nó thực hiện luồng hình ảnh HTTP vẽ trực tiếp vào canvasTính năng phóng to và kéo trong SurfaceView

Tôi đã thử mã sau và nó hoạt động ... nhưng nó cho tôi vấn đề trong biên giới. Không biết lý do tại sao. Bất kỳ giúp đỡ?

Full dòng:

full stream image

chỉnh tỷ lệ:

zoomed image

Trong ảnh thứ hai bạn có thể thấy nhiều dòng màu xanh lá cây mà không cần phải có mặt ở đó.

Đây là lớp học để xử lý dòng này:

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

Mã cho thêm các khung hình lên bề mặt như sau:

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

Trả lời

1

Mã bạn đăng là chưa đầy đủ nên khó khăn của mình để nói vấn đề là gì. Tôi đã thả mã của bạn vào một dự án demo nhanh và không thấy bất kỳ vấn đề nào với đường viền.

Chỉ bằng cách xem ảnh chụp màn hình: bất kỳ cơ hội nào mà dữ liệu hình ảnh của bạn bằng cách nào đó đang gói? Ảnh chụp màn hình thứ 2 trông giống như đường viền dưới cùng đang được vẽ ở đầu hình ảnh. Một lần nữa khó nói mà không có mã tái sản xuất.

Có thể thử sơn lại nền trước khi vẽ lại bitmap

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

Tôi đã thêm mã cho thêm các hình ảnh. Trên thực tế, nó sẽ tốt hơn rất nhiều khi sử dụng luồng chỉ đến nguồn tài nguyên hình ảnh HTTP .. nhưng hiện tại tôi chỉ tải xuống bitmap mỗi lần (không biết cách thay đổi) – Filnik

+0

Bạn có xóa nền sau mỗi lần vẽ không? (Cập nhật câu trả lời) – ayvazj

+0

xoá nền không hoạt động! Vấn đề duy nhất là khi tôi sử dụng các liên lạc để di chuyển zoom, không giới hạn ở các biên giới của hình ảnh. Làm việc trên đó. Mặc dù hiệu ứng zoom hiện đang hoạt động :) cảm ơn. Tôi sẽ sớm đăng một giải pháp đầy đủ – Filnik

Các vấn đề liên quan