programacion - manual de android en pdf
Zoom y funciĆ³n de arrastre en SurfaceView (1)
El código que has publicado está incompleto, por lo que es difícil decir cuál es el problema. Dejé caer su código en un proyecto de demostración rápida y no vi ningún problema con las fronteras.
Solo con mirar las capturas de pantalla: ¿existe alguna posibilidad de que los datos de su imagen se ajusten de alguna manera? La segunda captura de pantalla parece que el borde inferior se está dibujando en la parte superior de la imagen. Una vez más difícil de decir sin código reproducible.
Podría intentar volver a pintar el fondo antes de volver a dibujar el mapa de bits
canvas.drawRect(rect, backgroundPaint);
frame.drawBitmap(canvas, b, rect);
Estoy tratando de crear un SurfaceView que se puede ampliar y arrastrar. Implementa un flujo de imágenes HTTP que se dibuja directamente en el lienzo.
He probado el siguiente código y funciona un poco ... pero me da problemas en las fronteras. No tengo idea de la razón por la que. ¿Alguna ayuda?
Transmisión completa:
Imagen ampliada:
En la segunda imagen puedes ver varias líneas verdes que no necesitan estar allí.
Esta es la clase que maneja este flujo:
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;
}
}
El código para agregar los marcos a la superficie es el siguiente:
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;
}