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.