Questo post è stato scritto da Gabriele Gaggi, owner di Brain-sys s.r.l.
E’ inutile negarlo. Se dovessimo scegliere due buzzword che rappresentino gli ultimi 5 anni di evoluzione del mondo dell’informatica la scelta probabilmente ricadrebbe su: HTML5 e Mobile. I dati riportarti da Mary Meeker nel suo rapporto annuale su internet per KPCB riportano cifre da capogiro relative alla crescita degli utenti che navigano con device mobili: è un trend che non può più essere ignorato.
HTML5 e CSS3 non hanno bisogno di presentazioni: sono il vero acceleratore del web dal 2012 ad oggi e hanno rivoluzionato l’approccio ad Internet sia per chi fornisce contenuti sia per chi ne fruisce.
L’approccio web al mobile
Fortunatamente da tempo i web designer tengono conto delle esigenze dei dispositivi mobili. Numerose sono le filosofie ed i framework che si sono fatti strada nel tentativo di semplificare la vita di chi si trova ogni giorno a combattere con decine (se non centinaia) di risoluzioni diverse, browser diversi e user agent a volte bizzarri. Wurfl, progetto open source fondato dall’italianissimo Luca Passani, riporta all’interno del suo database ben 22.218 diversi user agent (fonte: file XML versione 2.3.5 scaricato dal sito ufficiale).
Tra i framework più famosi è d’obbligo citare Bootstrap e jQuery mobile, che approcciano il sito web per dispositivo mobile con filosofie diametralmente opposte: il primo basandosi sul concetto di design responsivo (qui un interessante articolo di Katrien De Graeve), mentre il secondo sul concetto di sito dedicato ai dispositivi mobili (per scoprire come applicare questa tecnica con ASP.NET Microsoft ha prodotto un esaustivo “How to”).
Far fruttare il know-how web: Apache Cordova
Nel 2015 non esiste web designer che non si sia trovato ad affrontare la questione mobile, questione quindi ben nota a chi mastica quotidianamente HTML5 e CSS3. Ebbene, questi designer, potenzialmente, hanno già ora il know-how adatto per poter diventare sviluppatori di app mobile, e per far sì che le app da loro create possano essere pubblicate agevolmente sugli store delle diverse piattaforme.
Nel lontano 2009 una fortunata azienda di nome Nitobi presentò un framework di sviluppo con questo semplice slogan: “PhoneGap Simplifies iPhone, Android, BlackBerry Development”. L’idea geniale fu di creare una sorta di web browser full screen, dove far girare applicazioni scritte utilizzando unicamente HTML5, CSS3 e Javascript, mettendo a disposizione di queste applicazioni delle API per l’interfacciamento al dispositivo. L’accoglienza fu positiva, ma non poteva non saltare all’occhio un problema legato alle performance: erano notevolmente ridotte rispetto a soluzioni native. Qualcuno però riuscì a guardare oltre e ad immaginare un futuro prossimo con web view ottimizzate e device più potenti. Quel futuro è ora, e quel progetto oggi ha un figlio open source dal nome Apache Cordova. Il momento è maturo per salire a bordo e far fruttare il proprio know-how web nell’ambito della produzione di applicazioni mobile.
Microsoft <3 Open Source
Microsoft, ad inizio 2014 con il rilascio della update 2 di Visual Studio 2013, rilascia l’estensione per “Multi-Device Hybrid App Development”, estensione attualmente nota con il nome di “Visual Studio Tools for Apache Cordova” e giunta proprio in questi giorni alla versione CTP 3.1. La stessa viene inclusa di default nell’installazione di Visual Studio 2015 CTP 6. Questa estensione consente lo sviluppo di applicazioni Apache Cordova direttamente utilizzando Visual Studio: senza mai abbandonare l’ambiente di sviluppo che utilizziamo abitualmente, possiamo creare, debuggare e predisporre i pacchetti per la pubblicazione delle nostre applicazioni mobile. Tutto questo non è per nulla triviale, dato che l’estensione predispone per noi l’installazione e la configurazione dei numerosi elementi necessari per lo sviluppo completo con Apache Cordova.
Un esempio: la calcolatrice
Allo scopo di illustrare la semplicità e rapidità di sviluppo con i Visual Studio Tools for Apache Cordova proviamo insieme a creare la classica calcolatrice dotata delle 4 funzionalità di base (Il sorgente completo dell’esempio è scaricabile da https://github.com/gaggiga/CordovaDemo). Al fine di adattare automaticamente il layout alla risoluzione dei diversi dispositivi utilizzeremo il già citato framework bootstrap.
Per cominciare è necessario creare un nuovo progetto utilizzando l’apposito template presente nella sezione Javascript -> “Apache Cordova Apps”.
Creato il nuovo progetto possiamo subito notare la struttura molto semplice e decisamente simile a quella che siamo abituati a vedere in un sito web. Abbiamo una pagina index.html che rappresenta il punto di ingresso della nostra applicazione ed una struttura di cartelle contenente pochi file, tra cui il relativo foglio di stile ed il file Javascript index.js. Merita di essere menzionato il file config.xml, che attraverso un apposito editor presente in Visual Studio ci permette di configurare tutti i dettagli della nostra applicazione: display name, start page e molto altro; tra cui l’attivazione dei plugin di cui abbiamo bisogno per interagire con il dispositivo mobile. Non ci soffermiamo a lungo su questi dettagli, di cui esiste molta letteratura sul web (indispensabile la documentazione presente in MSDN), il nostro obiettivo ora è di dare alla luce la nostra prima applicazione ibrida multi device. La pagina index.html è una semplice pagina HTML5 senza nessuna particolarità. Questo dovrebbe farci sentire a nostro agio. Il template di default include nell’header il foglio di stile index.css, e prima della chiusura del tag body, come ormai è consuetudine, tre script Javascript: cordova.js, platformOverrides.js e index.js.
· Cordova.js è il riferimento al framework Cordova, file che viene aggiunto automaticamente in fase di build e che non è tra quelli presenti nella solution.
· PlatformOverrides è un meccanismo che ci consente di scrivere codice personalizzato per le diverse piattaforme di destinazione. In fase di build viene sostituito con il corrispondente file dedicato alla piattaforma per cui stiamo compilando che è presente nella cartella merges.
· Infine arriviamo a index.js che andrà a contenere il codice per la gestione della nostra pagina.
Includiamo Bootstrap
Per assicurarci un aspetto piacevole e la responsività della pagina alle diverse risoluzioni è conveniente appoggiarsi ad un framework a cui far fare il lavoro sporco. Nello specifico la nostra scelta ricade sul noto framework Bootstrap. Ma per non appesantire più del necessario la nostra applicazione andremo ad includere solo ciò che effettivamente ci serve: il foglio di stile.
Per fare questo andiamo sul sito ufficiale di Bootstrap e scarichiamo l’ultima versione. Dal file .zip estraiamo solo il file bootstrap.min.css e lo andiamo a posizionare all’interno della cartella css del nostro progetto.
Appena prima dell’inclusione del file di stile index.css andiamo quindi ad includere il file di Bootstrap:
<link rel="stylesheet" href="css/bootstrap.min.css">
Il nostro obiettivo è di creare una calcolatrice responsiva. Quindi dovremo far sì che graficamente la stessa occupi l’intera larghezza e altezza dello spazio riservato alla nostra app sullo schermo. A questo scopo inseriamo il seguente tag nell’header della pagina, tag che toglie all’utente la possibilità di ingrandire il contenuto della nostra calcolatrice.
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
Disegniamo il layout
L’aspetto che vogliamo ottenere è quello della classica calcolatrice che consente di gestire le 4 funzionalità di base. A lato possiamo vedere l’aspetto finale con evidenziate in rosso le 4 macro aree che dobbiamo predisporre all’interno della pagina html.
Come anticipato desideriamo che la nostra calcolatrice sfrutti tutto lo spazio a disposizione sia in orizzontale che in verticale. L’occupazione orizzontale ci viene fornita direttamente dal framework bootstrap con l’uso della classe “container-fluid” da utilizzare sull’elemento base della nostra struttura. Per quanto riguarda invece l’occupazione verticale dobbiamo inserire nel file index.css una nuova classe dove indicare l’occupazione al 100% dell’altezza.
La stessa regola dobbiamo applicarla sia al tag html che al tag body:
html, body, .fullHeight {
height:100%;
}
Cominciamo quindi a dividere la nostra pagina nelle 4 macro sezioni indicate in figura, avendo l’accortezza di aggiungere la classi container-fluid e fullHeight all’elemento contenitore principale e la classe bootstrap “row” ad ogni sezione in modo che queste vengano appunto trattate come righe di una ipotetica tabella.
<div class="container-fluid fullHeight">
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
</div>
Di seguito andiamo ad inserire in ogni macro sezione i diversi contenuti: un div dove riportare il risultato nella prima sezione e 4 pulsanti nella seconda. La terza e la quarta sezione vanno a loro volta divise in due sotto sezioni orizzontali per consentire lo sviluppo su due righe del pulsante a destra. La prima sotto sezione conterrà quindi due nuove righe, ognuna composta da 3 pulsanti e la seconda il solo pulsante di destra.
Utilizzando le classiche classi di bootstrap per la suddivisione in 12 colonne di ogni riga, questo è il codice che andremo ad ottenere.
<div class="container-fluid fullHeight">
<div class="row">
<div id="casella" class="col-xs-12">0.0</div>
</div>
<div class="row">
<button class="col-xs-3 btn btn-default">C</button>
<button class="col-xs-3 btn btn-default">÷</button>
<button class="col-xs-3 btn btn-default">×</button>
<button class="col-xs-3 btn btn-default">-</button>
</div>
<div class="row">
<div class="col-xs-9">
<div class="row">
<button class="col-xs-4 btn btn-default">7</button>
<button class="col-xs-4 btn btn-default">8</button>
<button class="col-xs-4 btn btn-default">9</button>
</div>
<div class="row">
<button class="col-xs-4 btn btn-default">4</button>
<button class="col-xs-4 btn btn-default">5</button>
<button class="col-xs-4 btn btn-default">6</button>
</div>
</div>
<button class="col-xs-3 btn btn-default">+</button>
</div>
<div class="row">
<div class="col-xs-9">
<div class="row">
<button class="col-xs-4 btn btn-default">1</button>
<button class="col-xs-4 btn btn-default">2</button>
<button class="col-xs-4 btn btn-default">3</button>
</div>
<div class="row">
<button class="col-xs-8 btn btn-default">0</button>
<button class="col-xs-4 btn btn-default">.</button>
</div>
</div>
<button class="col-xs-3 btn btn-default">=</button>
</div>
</div>
Ora possiamo compilare e visualizzare il risultato della nostra fatica. Per fare questo è necessario compilare selezionando dall’apposita combo nella toolbar principale una delle piattaforme supportate. Di default all’avvio viene selezionata la piattaforma Android, ma come possiamo vedere dall’immagine è possibile selezionare una qualunque delle altre piattaforme presenti. Un discorso a parte merita iOS, che, causa policy di Apple, richiede il possesso di un computer Mac per poter compilare e debuggare le app. Al seguente link è possibile trovare maggiori dettagli in merito: https://msdn.microsoft.com/en-us/library/dn771551.aspx
Una volta selezionata la piattaforma, nella combo alla sua sinistra, dobbiamo selezionare dove eseguire l’applicazione. Per quanto riguarda Android ed iOS è presente l’emulatore Ripple con le sue diverse configurazioni ma esiste anche la possibilità di utilizzare altri emulatori / simulatori ed addirittura di eseguire il codice direttamente su un device connesso al pc. Analoghe, ma con emulatori nativi, le soluzioni per Windows Phone e per Windows 8.1.
Fatte queste selezioni, per esempio Android e Ripple – Nexus (Galaxy), possiamo compilare ed eseguire il codice premendo il tasto F5 sulla tastiera. Il risultato che verrà mostrato non è troppo lontano dall’aspetto desiderato: dobbiamo innanzitutto occuparci dello spazio verticale.
Occupiamo tutta l’altezza
Per fare questo torniamo al file index.css, dove andiamo ad aggiungere anche i button alla regola del 100% di altezza: questi devono infatti occupare il 100% dell’altezza a loro disposizione. Aggiungiamo inoltre al foglio di stile le specifiche di allineamento del testo per la casella che mostra il risultato e quattro classi utili per la distribuzione dello spazio disponibile in altezza. Decidiamo di voler impostare il 15% dell’altezza totale come spazio dedicato ad ogni singola riga di pulsanti. Quindi le macro sezioni contenenti due righe dovranno necessariamente occupare il 30% di spazio. Creeremo quindi le seguenti classi:
.singleRow { height:15%; }
.doubleRow { height:30%; }
La prima andiamo ad applicarla solo sulla seconda macro sezione, che è effettivamente costituita da una singola fila di pulsanti. La seconda classe la utilizziamo per le due macro sezioni successive, ognuna composta da due file di pulsanti.
Per completare il lavoro abbiamo bisogno di altre due classi. La prima segnala di occupare la metà dell’altezza a disposizione, ci serve per dividere equamente le ultime due macro sezioni.
.halfHeight { height:50%; }
La seconda è necessaria per assegnare lo spazio restante alla casella del risultato:
.quarterHeight { height:25%; }
Adattiamo le dimensioni dei caratteri
Rimane un’ultima cosa per definire la grafica e renderla totalmente responsiva: le dimensioni del font. Per fare questo dobbiamo necessariamente intervenire con del codice Javascript. Visto che si tratta di poco codice, senza particolari complessità, andiamo ad inserirlo direttamente nel file index.js. Qui rimuoviamo il codice predefinito, utile per gestire eventuali salvataggi di stato dell’applicazione, ma non necessario nel nostro esempio. Inseriamo quindi del codice che ci consenta di effettuare il resize del font alle diverse risoluzioni. L’approccio è quello di creare una funzione che imposti le dimensioni del testo pari ad una percentuale fissata delle dimensioni del suo contenitore. La funzione deve essere richiamata una prima volta a seguito del caricamento della pagine, ed ogni qualvolta le dimensioni della pagina cambieranno.
Di seguito il codice commentato in ogni parte:
(function () {
"use strict";
// L'elemento casella viene utilizzato più volte quindi vale la pena
// estrarlo in una variabile globale
var casella = document.getElementById('casella');
// Funzione che effettua il resize del font
function resizeFont() {
// Lettura dell'array button presenti nella pagina
// e lettura dell'altezza effettiva assunta dal primo di essi
var buttons = document.getElementsByTagName('button');
var buttonHeight = parseInt(buttons[0].offsetHeight);
// Calcolo del fontSize da impostare sui button pari al 50%
// dell'altezza dei button stessi
var fontSize = Math.round(buttonHeight * 0.5) + "px";
// Impostazione del font per ogni button presente nella pagina
for (var i = 0; i < buttons.length; i++) {
buttons[i].style.fontSize = fontSize;
}
// Lettura dell'altezza effettiva assunta dalla casella
var casellaHeight = parseInt(casella.offsetHeight);
// Impostazione del font size al 40% dell'altezza contenitore
// e del line-height al 100% dell'altezza del contenitore per centrare
// il testo verticalmente
casella.style.fontSize = Math.round(casellaHeight * 0.4) + "px";
casella.style.lineHeight = casellaHeight + "px";
}
// Chiamata alla funzione di resize del font al variare delle dimensioni della finestra
window.addEventListener('resize', resizeFont);
// Prima chiamata alla funzione
resizeFont();
})();
E con quest’ultima modifica possiamo ritenerci soddisfatti: l’aspetto grafico risulta piacevole ed il layout si adatta automaticamente alle diverse risoluzioni disponibili. Ora è necessario implementare le funzionalità.
Javascript clean code
Javascript è un linguaggio di programmazione allo stesso tempo molto amato e molto odiato. La tendenza ad utilizzarlo un po’ ovunque è la chiara dimostrazione di quanto sia amato (last but not least Node.js). La smodata crescita di linguaggi che cercano di migliorarlo dimostrano quantomeno che l’uso disordinato di questo linguaggio può essere spiacevole (a risoluzione definitiva di tutto questo è importante citare l’indispensabile TypeScript).
Senza complicarci troppo la vita cerchiamo di utilizzare Javascript nel modo più pulito possibile, seguendo best practices ormai universalmente riconosciute. Andiamo quindi a creare un nuovo file chiamato calcolatrice.js all’interno della cartella scripts. Qui inseriremo il codice necessario per gestire la nostra calcolatrice.
In particolare andiamo a creare una classe Calcolatrice dotata di costruttore, di un metodo da richiamare per inserire una nuova cifra numerica (nuovaCifra) e di un metodo da richiamare per inserire una nuova operazione (nuovaOperazione). Infine Calcolatrice mette a disposizione la proprietà testo che contiene il testo da mostrare nella casella del risultato e l’evento testoCambiato per notificare il variare del valore della proprietà testo.
var Calcolatrice = (function () {
function Calcolatrice() {
...
this.testo = "0";
}
Calcolatrice.prototype = {
constructor: Calcolatrice,
nuovaCifra: nuovaCifra,
nuovaOperazione: nuovaOperazione,
addListenerTestoCambiato: addListenerTestoCambiato,
...
}
return Calcolatrice;
...
})();
Il codice completo è scaricabile a questo indirizzo:
https://github.com/gaggiga/CordovaDemo/blob/master/Calcolatrice/scripts/calcolatrice.js
Creata la classe pronta a gestire la nostra calcolatrice, ora è necessario agganciarla all’interfaccia. A questo scopo andiamo ad identificare nell’html i pulsanti che se premuti dovranno richiamare il metodo nuovaCifra, e quelli che se premuti dovranno richiamare il metodo nuovaOperazione. Banalmente aggiungiamo la classe css cifra al primo gruppo (pulsanti numerici e separatore decimale) e la classe css operazione al secondo gruppo (pulsanti delle 4 operazioni, di azzeramento e di uguale).
<button class="col-xs-3 btn btn-default operazione">C</button>
...
<button class="col-xs-4 btn btn-default cifra">7</button>
Inseriamo infine il seguente codice Javascript nel file index.js per completare la connessione tra l’interfaccia e la classe calcolatrice.
// Istanza di calcolatrice
var calcolatrice = new Calcolatrice();
// Recupero dei button delle cifre e delle operazioni
var cifre = getElementsByClass('cifra');
var operazioni = getElementsByClass('operazione');
// Gestione del click sulle cifre
for (var i = 0; i < cifre.length; i++) {
cifre[i].addEventListener('click', function (e) {
calcolatrice.nuovaCifra(e.target.innerText);
});
}
// Gestione del click sulle operazioni
for (var i = 0; i < operazioni.length; i++) {
operazioni[i].addEventListener('click', function (e) {
calcolatrice.nuovaOperazione(e.target.innerText);
});
}
// Gestione dell'evento testoCambiato
calcolatrice.addListenerTestoCambiato(function (e) {
casella.innerText = calcolatrice.testo;
});
La nostra calcolatrice è terminata. Grazie ai diversi emulatori / simulatori installati con Visual Studio possiamo testare il funzionamento e verificare l’aspetto sulle diverse piattaforme supportate, o addirittura verificare immediatamente su dispositivi reali. Dispositivi che però devono essere stati predisposti in precedenza a questo scopo (qui le istruzioni per Windows Phone, qui per Android e qui per iOS).
Deploy sugli store
Completato lo sviluppo, configurati gli asset relativi alle diverse piattaforme (icona, splash screen ecc.), è arrivato il momento di predisporre i pacchetti da pubblicare sui diversi store. Anche in questo Visual Studio ci assiste consentendoci di generare e firmare i package per Android, iOS, Windows 8 e Windows Phone 8. Compito nostro sarà quello di sottomettere al processo di approvazione l’applicazione.
Consigli utili
Con il medesimo sforzo con cui avremmo creato un’applicazione web abbiamo creato una vera e propria app pubblicabile sugli store dei diversi dispositivi mobili, il tutto senza mai abbandonare Visual Studio.
Nell’intero processo ci sono due criticità da tenere in considerazione:
- L’interfaccia utente: Dobbiamo fare attenzione a rispettare i requisiti dei differenti store per assicurarci l’approvazione. Sta a noi decidere se uniformare l’interfaccia per tutti gli store o se effettuare delle specifiche personalizzazioni per agevolarne l’uso agli utenti dei diversi sistemi operativi. A mio parere questo secondo approccio è preferibile e non richiede un grosso sforzo. Qui una serie di link che potranno guidarci per assicurarci l’approvazione dei diversi store.
- Il codice Javascript: E’ fondamentale la pulizia e l’ordine del codice: con un linguaggio non tipizzato l’entropia cresce in modo esponenziale al crescere dell’applicazione, quindi è vitale darsi delle regole e scrivere codice pulito, magari facendo uso di TypeScript. Dedichiamo anche un po’ di tempo a rintracciare soluzioni performanti: i dispositivi su cui potrà girare la nostra app hanno le caratteristiche più disparate, e l’obiettivo dovrebbe essere quello di raggiungere la maggior parte di potenziali utenti.
Infine suggerisco di non abusare di framework di terze parti. Se è vero che Cordova ci consente di utilizzare qualunque framework CSS / Javascript questo non vuol dire che siamo obbligati a farlo. Escludendoli avremo l’effetto di rallentare un po’ i tempi di sviluppo, ma eviteremo di appesantire inutilmente la nostra app.
Risorse
Ricordo che il progetto completo è liberamente scaricabile da qui.
Taming Mobile Apps with Cordova and Visual Studio
Using Cordova and Visual Studio to build iOS Mobile Apps
OOP In JavaScript: What You NEED to Know
Mobile Development Platform Performance (Native, Cordova, Classic Xamarin, Xamarin.Forms)
Mobile Development Platform Performance Part 2 (Native, Cordova, Classic Xamarin, Xamarin.Forms)
read full article