Saltar para conteúdo


Foto
- - - - -

Problema com limites de Pan e Zoom, usando canvas e bitmap

view canvas bitmap zoom pan

  • Por favor inicie sessão para responder
Não há respostas a este tópico.

#1 MarcoAF

MarcoAF

    Novato

  • Membros
  • Pip
  • 3 mensagens
  • Samsung Galaxy S4

Mensagem publicada 26 February 2015 - 10:50

Estou com um problema em definir os limites para o zoom e pan. Criei uma classe que extende a classe View para desenhar um bitmap num canvas. Inicialmente passo a imagem original por um método para a minha classe, torno esse bitmap mutável e defino o escalamento para a imagem ficar escalada em relação à minha view que contem o canvas, chamo invalidate() e o desenho é feito. Depois consigo fazer zoom e pan sem qualquer problema, ou seja até aqui tudo bem. O problema está em definir os limites para mostrar apenas a imagem, de modo a quando faço zoom out a imagem não fique muito pequena em relação à minha view e quando faço drag a imagem não ultrapasse os limites superior, inferior, direito e esquerdo. A minha view tem uma largura de 1239 e uma altura de 726.

No método que recebe o bitmap tenho isto:

public void setMyBitmap(Bitmap bmp){
    myBitmap = bmp.copy(Bitmap.Config.RGB_565, true);
    float sx = ((float) 1239) / (float)(myBitmap.getWidth());
    float sy = ((float) 726) / (float)(myBitmap.getHeight());
    matrix.setScale(sx, sy);

    invalidate();
}

No onTOuchEvent tenho o seguinte:

@Override
public boolean onTouchEvent(MotionEvent event) {

    switch(event.getAction()&MotionEvent.ACTION_MASK){
    case MotionEvent.ACTION_DOWN:
        savedMatrix.set(matrix);
        start.set(event.getX(0), event.getY(0));
        Log.d(TAG, "ACTION_DOWN -> mode=DRAG");
        mode = DRAG;
        break;
    case MotionEvent.ACTION_POINTER_DOWN:
        oldDist = spacing(event);//calcula a distancia entre dois pontos (teorema pitagoras)
        Log.d(TAG,"ACTION_POINTER_DOWN -> mode=ZOOM");
        if (oldDist > 10f) {
            savedMatrix.set(matrix);
            midPoint(mid,event);//calcula o pontoo medio de dois pontos
            mode=ZOOM;
        }
        break;
    case MotionEvent.ACTION_UP:
        mode = NONE;
        Log.d(TAG,"ACTION_UP");
    case MotionEvent.ACTION_POINTER_UP:
        mode = NONE;
        Log.d(TAG,"ACTION_POINTER_UP -> mode=NONE");
        break;
    case MotionEvent.ACTION_MOVE:
        if(mode==DRAG){
            Log.d(TAG,"ACTION_MOVE -> mode=DRAG");
            matrix.set(savedMatrix); 
            float dX = event.getX(0) - start.x;
            float dY = event.getY(0) - start.y;
            matrix.postTranslate(dX,dY);

            //QUANDO ESTAMOS NO MODO DRAG DEFINE OS LIMITES DIREITO E INFERIOR
            float[] values = new float[9];
            matrix.getValues(values);
            if((1239*scale + values[2] < 1239)){
                values[2] = 1239*(1-scale);
                matrix.setValues(values);
            }
            if(726*scale + values[5] < 726){
                values[5] = 726*(1-scale);
                matrix.setValues(values);
            }
        }else if(mode==ZOOM){
            float newDist = spacing(event);
            Log.d(TAG,"ACTION_MOVE -> mode=ZOOM");
            matrix.set(savedMatrix);
            scale = newDist / oldDist;
            matrix.postScale(scale, scale, mid.x, mid.y);

            //QUANDO ESTAMOS NO MODO ZOOM DEFINE OS LIMITES DE ZOOM (LEFT TOP RIGHT BOTTOM)
            float[] values = new float[9];
            float sx = ((float) 1239) / (float)(myBitmap.getWidth());
            float sy = ((float) 726) / (float)(myBitmap.getHeight());
            matrix.getValues(values);
            if(values[0] < sx || values[4] < sy){
            matrix.setScale(sx, sy, 1239/2, 726/2);
            }
        }
        break;
    }

    //QUANDO ESTAMOS NO MODO DRAG DEFINE OS LIMITES SUPERIOR E ESQUERDO
    float[] values = new float[9];
    matrix.getValues(values);
    if(values[2] > 0){ values[2] = 0; matrix.setValues(values);}
    if(values[5] > 0){ values[5] = 0; matrix.setValues(values);}

    invalidate();

    return true;
}

Defini o scale como variável global do tipo float para utilizar na imposição dos limites.

No onDraw basicamente tenho isto:

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    canvas.drawBitma(myBitmap, matrix, mPaint);
}

O problema acho que está relacionado com o facto de ao tocar o ecrã com um dedo para fazer zoom ou pan, se eu quiser fazer zoom ele automaticamente entra no modo pan, e altera os valores da matrix, isto pois existe sempre uma diferença o tempo de colocação dos dois dedos. O problema poderá ser de como os modos estão definidos (DRAG, ZOOM, NONE). Se eu tirar estes limites tudo funciona bem, mas eu quero que a minha view apenas mostre imagem e nada mais. Alguém me consegue ajuda? Já estou à bastante tempo de volta disto e não consigo resolver o problema.Obrigado


Editado por MarcoAF, 26 February 2015 - 10:55.






Também marcado com uma ou mais destas tags: view, canvas, bitmap, zoom, pan