2012-11-25 8 views

risposta

0

Attuazione del Pinch Zoom Gesto

Il pinch zoom gesto è simile al movimento di trascinamento, tranne che inizia quando il secondo dito premuto sullo schermo (ACTION_POINTER_DOWN).

 
case MotionEvent.ACTION_POINTER_DOWN: 
oldDist = spacing(event); 
Log.d(TAG, "oldDist=" + oldDist); 
if (oldDist > 10f) { 
savedMatrix.set(matrix); 
midPoint(mid, event); 
mode = ZOOM; 
Log.d(TAG, "mode=ZOOM"); 
} 
break; 


case MotionEvent.ACTION_MOVE: 
if (mode == DRAG) { 
// ... 
} 
else if (mode == ZOOM) { 
float newDist = spacing(event); 
Log.d(TAG, "newDist=" + newDist); 
if (newDist > 10f) { 
matrix.set(savedMatrix); 
float scale = newDist/oldDist; 
matrix.postScale(scale, scale, mid.x, mid.y); 
} 
} 
break; 

Quando si ottiene l'evento di discesa per il secondo dito, calcoliamo e ricordiamo la distanza tra le due dita. Nei miei test, Android a volte mi diceva (erroneamente) che c'erano due dita premute quasi esattamente nella stessa posizione. Quindi ho aggiunto un segno di spunta per ignorare l'evento se la distanza è minore di un numero arbitrario di pixel. Se è più grande, ricordiamo la matrice di trasformazione corrente, calcoliamo il punto medio delle due dita e iniziamo lo zoom.

Quando arriva un evento di spostamento mentre siamo in modalità zoom, calcoliamo nuovamente la distanza tra le dita. Se è troppo piccolo, l'evento viene ignorato, altrimenti ripristiniamo la matrice di trasformazione e ridimensioniamo l'immagine attorno al punto medio.

La scala è semplicemente il rapporto tra la nuova distanza divisa per la vecchia distanza. Se la nuova distanza è più grande (ovvero le dita si sono allontanate ulteriormente), la scala sarà maggiore di 1, ingrandendo l'immagine. Se è più piccolo (dita ravvicinate), la scala sarà inferiore a uno, rendendo l'immagine più piccola. E ovviamente se tutto è uguale, la scala è uguale a 1 e l'immagine non è cambiata.

Ora definiamo i metodi spaziatura() e midPoint().

distanza tra due punti

Per scoprire quanto lontano a parte due dita sono, per prima cosa costruire un vettore (x, y), che è la differenza tra i due punti.

Poi usiamo la formula per distanza euclidea per calcolare la spaziatura:

 
private float spacing(MotionEvent event) { 
float x = event.getX(0) - event.getX(1); 
float y = event.getY(0) - event.getY(1); 
return FloatMath.sqrt(x * x + y * y); 
} 

L'ordine dei punti non importa, perché tutti i segni negativi verranno perse quando li abbiamo quadrati. Nota che tutta la matematica viene eseguita utilizzando il tipo float di Java. Mentre alcuni dispositivi Android potrebbero non avere hardware in virgola mobile, non lo facciamo abbastanza spesso da preoccuparci delle sue prestazioni.

punto medio di due punti

Calcolare un punto nel mezzo di due punti è ancora più facile:

 
private void midPoint(PointF point, MotionEvent event) { 
float x = event.getX(0) + event.getX(1); 
float y = event.getY(0) + event.getY(1); 
point.set(x/2, y/2); 
} 

Tutto quello che facciamo è prendere la media del loro coordinate X e Y. Per evitare raccolte di dati inutili che possono causare pause notabili nell'applicazione, riutilizziamo un oggetto esistente per archiviare il risultato anziché allocarlo e restituirne uno nuovo ogni volta. Prova a eseguire il programma ora sul tuo telefono. Trascina l'immagine con un dito e ingrandiscila pizzicando le dita dentro o fuori. Per ottenere i migliori risultati, non lasciare che le dita si avvicinino di un pollice o due. Altrimenti inizierai a incappare in alcuni di questi bug nell'API che ho menzionato prima.

This is an excerpt from Hello, Android 3rd edition, published by the Pragmatic Bookshelf. For more information or to purchase a paperback or PDF copy, please visit http://www.pragprog.com/titles/eband3

Problemi correlati