Cerca con Google

Translate

17 novembre 2015

MIT App Inventor - MultiTouch e Pinch to Zoom


Continuiamo a parlare di MIT App Inventor e delle nuova funzionalità "Extension".

MIT App Inventor può essere utilizzato per realizzare app Android in modo facile e divertente.

Come introdotto nel post precedente (MIT App Inventor extensions) sono da poco disponibili dei componenti aggiuntivi per App Inventor chiamati appunto extensions.

Ogni estensione ha un compito ben preciso e può essere aggiunta ai propri progetti caricando il relativo file .aix, con questo approccio modulare App Inventor diventa ancora più potente restando al tempo stesso semplice ed immediato per chi si avvicina per la prima volta alla programmazione di Android App.


Nel mini tutorial di oggi vi voglio mostrare il lavoro svolto da Hal Habelson (docente e sviluppatore del MIT) relativo all'estensione per il MultiTouch.
Come sapete ormai tutti i moderni smartphone supportano il MultiTouch, ovvero la possibilità di riconoscere contemporaneamente più tocchi sullo schermo.

Il principale utilizzo del MultiTouch lo si ha nell'implementazione di quello che comunemente viene chiamato Pinch-to-Zoom o gesture Pinch-In / Pinch-Out per lo zoom di un elemento della propria app (tipicamemte un immagine, una mappa, etc...).

Attualmente MIT App Inventor non gestisce direttamente il MultiTouch (lo si può avere solo all'interno di una pagina html visualizzata tramite componente webviewer), ma tramite l'aggiunta di una estensione specifica possiamo per ora ottenere un semplice effetto pinch to zoom.

Per cominciare scarichiamo l'estensione necessaria, che si trova nel "repository" ufficiale delle estensioni di App Inventor:
http://appinventor.mit.edu/extensions/
Selezioniamo l'estensione "ScaleDetector" che è quella che ci aiuterà nel nostro intento, salviamo il file ScaleDetector.aix sul nostro pc.

La documentazione ufficiale per questa estensione è disponibile cliccando QUI , vi consiglio di leggerla attentamente (anche se in inglese).

Tenete presente che le extensions sono ancora in fase beta, quindi potreste avere malfunzionamenti e problemi vari, sia col server sperimentale che con l'estensione qui utilizzata...il tutto si dovrebbe stabilizzare nei prossimi mesi.

L'estensione ScaleDetector è molto semplice ed ha un solo metodo ed un solo evento:


Per prima cosa bisogna "collegare" il componente ScaleDetector ad un Canvas esistente nella nostra app (ricordo quindi che lo ScaleDetector lavora solo componenti di tipo Canvas, ovvero componenti della nostra interfaccia utente in cui visualizzare altri componenti grafici come Ball o Sprite).

Dopodichè ad ogni gesture di Pinch-In (avvicinamento delle due dita) o Pinch-Out (allontanamento delle due dita) verrà generato l'evento ScaleDetector1.Scale ed il valore "scaleFactor" assumerà un valore numerico; maggiore di 1 se la gesture è di tipo Pinch-Out, minore di 1 se la gesture è di tipo Pinch-In (sarà tutto più chiaro quando vedrete l'esempio in azione, tranquilli!)

Il componente non fa molto altro (almeno al momento) ma il solo evento .Scale ci è già sufficiente per creare una semplice android app in cui un componente "Ball" viene ingrandito o rimpicciolito in base alla gesture eseguita dall'utente.

Per prima cosa quindi creiamo il nostro progetto sul server sperimentale di MIT App Inventor che supporta le extensions (attenzione che è diverso dal server che avete usato finora):

http://extension-test.appinventor.mit.edu/

E creiamo una nuova app, chiamata "Extension_ScaleBall", ovviamente in quest'app dobbiamo aggiungere l'extension ScaleDetector (vedi questo post per vedere come si caricano le estensioni http://seblogapps.blogspot.be/2015/11/mit-app-inventor-extensions-ottime.html)

A questo punto avremo la nostra nuova estensione ScaleDetector disponibile nella palette "Extension"

In questa semplice app dimostrativa voglio solo inserire un elemento "Ball" in un "Canvas" e fare in modo che con le famose gesture Pinch-In/Out si ottenga un effetto di zoom della sfera.

Aggiungiamo quindi una label (dove visualizzeremo dei valori di debug), un Canvas (dove posizioneremo il nostro componente "Ball" ed infine la "Ball"):


Ecco come appare la nostra interfaccia dell'app, ovviamente lascio al lettore la possibilità di cambiare la dimensione iniziale della Ball, il colore e tutto il resto a proprio piacere.

Spostiamoci quindi ora in Blocks Editor, e vediamo le proprietà di questo nuovo componente aggiunto dalla palette Extension:


Come detto a inizio articolo, dobbiamo per prima cosa "collegare" il componente al nostro Canvas, quindi in Screen1.Initialize (ovvero il blocco di codice eseguito al lancio dell'applicazione) agganciamo i due componenti con la chiamata al metodo .AddHandlerToCanvas



Inoltre posizioniamo la sfera al centro del canvas, quindi a metà della misura Width per l'asse x , e della misura Height per l'asse y a cui sottraiamo il raggio della sfera (più avanti capirete il perchè...).
Così anche se la nostra app girerà su schermi con risoluzioni diverse, sarà sempre centrata.

Ora veniamo al "cuore" del codice, ovvero il blocco di codice da eseguire quando l'utente effettua la gesture, come detto prima se le due dita si avvicinano scaleFactor  avrà un valore minore di 1, se si allontanano maggiore di 1.

Il componente ScaleDetector genera un evento .Scale ad ogni rilevazione della gesture, questo evento viene generato anche molte volte in un secondo a seconda del movimento delle dita rilevato.
Noi vogliamo rimpicciolire o ingrandire di un determinato numero di pixel il raggio della sfera ad ogni evento, limitando comunque i valori del raggio all'interno di un range minimo e massimo.

La soluzione proposta da Hal Habelson (a cui ovviamente vanno i miei ringraziamenti) è la seguente:


Qui sopra c'è tutta la "base" del ragionamento; in pratica con una condizione If controllo se devo ingrandire o ridurre il raggio, se lo devo ingrandire (get scaleFactor >= 1) imposto il nuovo raggio della sfera al valore minimo tra l'altezza di metà canvas o il valore del raggio aumentato di 3 pixel.
In questo modo la sfera non verrà mai disegnata con un raggio più grande della misura dello schermo e se è più piccolo di questo valore ad ogni movimento delle dita ingrandirò la pallina di 3 pixel.
Se invece scaleFactor è minore di 1 rimpicciolisco di 3 pixel il raggio ad ogni evento, a meno che non abbia già raggiunto la misura minima impostata nel codice (in questo caso di 5 pixel).

Potete provare questa implementazione, la cosa funziona ma ho pensato di applicare un pò di "ottimizzazioni" per farla funzionare meglio...

Infatti il problema con questo codice è che lo zoom sposta anche la sfera sullo schermo, infatti se vedete il codice cambia il raggio ma non la posizione della sfera.
Però in App Inventor il componente Ball è internamente disegnato come una sfera all'interno di un quadrato, e la coordinata x,y del componente rappresenta l'angolo superiore sinistro di questo quadrato, come vedete in questo disegno:
Quando quindi variamo il raggio R (Radius) avremo anche uno spostamento della sfera che non trovo corretto in un effetto di pinch to zoom.

Per risolvere la cosa ho allora modificato il codice, rendendolo leggermente più complicato.
All'evento .Scale oltre a variare il raggio sposto anche le coordinate x,y della sfera di un valore pari all'incremento/decremento del raggio.
Se quindi ad esempio il raggio aumenta di 3 pixel, ridisegno la sfera alle nuove coordinate x,y a cui sottraggo 3 pixel, in modo che la posizione del centro della sfera non cambi.

In questo modo quando si fa il Pinch-to-Zoom la sfera rimarrà ferma nella sua posizione.

Inoltre ho preferito parametrizzare il valore dell'incremento del raggio, aggiungendo la variabile globale che ho chiamato scaleValue per far si che lo zoom possa avvenire più o meno velocemente a seconda delle preferenze del programmatore.
Ho anche creato la costante minBallRadius che specifica il raggio minimo della sfera.

Invece di usare la funzione "min / max" ho preferito un approccio più tradizionale con altre condizioni "if" per non far ingrandire o rimpicciolire la sfera oltre i due valori massimi e minimi del raggio preimpostati.

Ecco quindi il codice finale del mio blocco per il pinch to zoom:


Per finire ho aggiunto un blocco che sposta la sfera così ridimensionata nel punto in cui l'utente tocca il Canvas.
Mi piacerebbe che l'effetto pinch to zoom funzionasse solo se l'utente effettivamente fa la gesture "sopra" l'oggetto stesso ma non avendo modo di capire quando le dita sono effettivamente sulla sfera all'interno dell'evento .Scale mi sono dovuto "accontentare" ...

Ho aggiunto la stampa dei valori delle coordinate x,y e l'indicazione se l'utente ha toccato la sfera o meno, giusto a scopo di debug.

Ecco il risultato finale della nostra android app con supporto al Multitouch e al Pinch to Zoom creata con MIT App Inventor!!!


Per scaricare il sorgente dell'app salvate sul vostro pc il file .aia da qui sotto, ricordo che il file .aia ha al suo interno già l'estensione necessaria "ScaleDetector", se invece volete partire da un progetto nuovo ricrodatevi di aggiungere l'estensione come spiegato ad inizio articolo.

Il file sorgente del progetto .aia è scaricabile cliccando QUA

Vi voglio anche mostrare quello che faremo nel prossimo tutorial, ovvero utilizzare ScaleDetector per implementare il Pinch to Zoom di uno Sprite , il codice sarà molto simile, quindi se non volete aspettare, perchè non provate da soli a farlo già da oggi???




Che ne pensate? Avete altre idee su come si potrebbe migliorare la gestione del Multitouch in App Inventor?
Buon App Inventing!!!







7 commenti:

  1. For any kind of apps?
    Great info! I appreciated about it.
    You can get more info on android apps here - apps on red.

    RispondiElimina
  2. questa estensione si puo usare pure con le foto.

    RispondiElimina
    Risposte
    1. Certo, come vedi basta inserire una foto come sprite e poi il procedimento sarà il medesimo (cambia solo il calcolo delle coordinate x,y quando si fa il ridimensionamento).

      Elimina
  3. Ciao Sebastiano, potresti essere così gentile da spiegare in dettaglio come utilizzare l'estensione su una foto? Grazie

    RispondiElimina
    Risposte
    1. Ora non trovo il tempo per farlo, cercherò cnq di accontentarti al più presto!

      Elimina
  4. Ciao :)
    Prima di tutto volevo ringraziarti per tutti i tutorial che hai realizzato e grazie ai quali io e tre miei amici, (siamo ragazzi del 5° liceo scientifico), ci siamo avvicinati al mondo della programmazione imparando a programmare con app inventor 2.
    Detto ciò, volevo dirti che siamo anche riusciti a realizzare un giochino matematico che è piaciuto moltissimo ai nostri amici così da convincerci a pubblicarlo, (chiaramente gratis e senza pubblicità), su Google Play. Per noi sarebbe veramente importante avere un tuo parere, di modo da poter scegliere se è il caso di trasferirci su AI2 a pagamento per risolvere qualche problema che tuttora persiste su alcuni telefoni (crash se giochi a lungo…).

    Questo è il link:
    https://play.google.com/store/apps/details?id=appinventor.ai_scrappsociety.Six

    Se hai tempo di rispondermi l'e-mail è francesco.alborino@savoiabenincasa.it

    Grazie mille per tutto!

    RispondiElimina
  5. Seopoly is a main incorporated programming, Apps, site improvement and computerized advertising corporate. We have practical experience in SEO-accommodating site building, app inventor, spot Net framework outlines and open source arrangements. Our group is committed to giving you predominant quality items and benefit and our consumer loyalty record are our reward.

    RispondiElimina