Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 ·...

61
Tecnologie - Classe Quinta prof. Diego Belliardo Xamarin pag 1 Android con l’utilizzo di Xamarin Rev Digitale 1.0 del 10/01/2020 Sommario Android SDK .......................................................................................................................................... 4 Ambiente di sviluppo ....................................................................................................................... 5 Programmazione in Android Studio .................................................................................................... 6 Programmazione in Visual Studio C# con Xamarin ............................................................................ 6 Componenti di Xamarin .................................................................................................................. 6 Requisiti ............................................................................................................................................. 8 Installazione con Visual Studio 2017 .................................................................................................. 8 Configurazione Xamarin ..................................................................................................................... 9 Android SDK Manager...................................................................................................................... 10 Emulatore Android............................................................................................................................ 11 Dispositivo fisico Android.................................................................................................................. 11 Creazione di applicazioni tramite Visual Studio .................................................................................... 11 Il primo esercizio .............................................................................................................................. 12 Activity .......................................................................................................................................... 12 Layout ........................................................................................................................................... 13 La classe Resource ...................................................................................................................... 14 Il file Resources / values / strings.xml ............................................................................................... 14 Il file AndroidManifest.xml ................................................................................................................. 14 Lancio dell’applicazione.................................................................................................................... 16 Widget e View .................................................................................................................................. 16 Accesso ai controlli : La proprietà numerica id ............................................................................. 16 La Gestione degli eventi ................................................................................................................... 17 1° soluzione (direi la più comoda) ................................................................................................. 17 2° soluzione .................................................................................................................................. 17 3° Soluzione Associazione di una procedura di evento tramite il designer .................................... 17 Associazione di uno stesso evento a più controlli ......................................................................... 18 L’evento onTouch ......................................................................................................................... 18 Il concetto di Context ........................................................................................................................ 19 Le finestre di pop up : i Toast ........................................................................................................... 19 AlertDialog........................................................................................................................................ 20 Utilizzo di un unico Listener .......................................................................................................... 21 Input Dialog ...................................................................................................................................... 21 Controlli e Proprietà ............................................................................................................................. 22 La scalatura delle immagini PX vs DP................................................................................................ 22 Istruzioni per la converione da px a dp .......................................................................................... 23 La casella di testo : il widget EditText .............................................................................................. 23 La gestione delle immagini : il widget ImageView ......................................................................... 24 Il metodo Resources.GetIdentifier() .............................................................................................. 24 Gestione dello schermo .................................................................................................................... 25 Rotazione dello schermo............................................................................................................... 25 Lettura delle Dimensioni dello schermo......................................................................................... 25 Check Box e Radio Button ............................................................................................................... 25 Impostazione delle proprietà tramite designer .................................................................................. 26 Impostazione delle proprietà tramite codice...................................................................................... 27 Le proprietà di tipo layout .............................................................................................................. 27 Creazione Dinamica dei controlli .......................................................................................................... 28 Note sulla gestione dell’Id................................................................................................................. 28

Transcript of Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 ·...

Page 1: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 1

Android con l’utilizzo di Xamarin

Rev Digitale 1.0 del 10/01/2020

Sommario Android SDK .......................................................................................................................................... 4

Ambiente di sviluppo ....................................................................................................................... 5 Programmazione in Android Studio .................................................................................................... 6 Programmazione in Visual Studio C# con Xamarin ............................................................................ 6

Componenti di Xamarin .................................................................................................................. 6 Requisiti ............................................................................................................................................. 8 Installazione con Visual Studio 2017 .................................................................................................. 8 Configurazione Xamarin ..................................................................................................................... 9 Android SDK Manager ...................................................................................................................... 10 Emulatore Android ............................................................................................................................ 11 Dispositivo fisico Android .................................................................................................................. 11

Creazione di applicazioni tramite Visual Studio .................................................................................... 11 Il primo esercizio .............................................................................................................................. 12

Activity .......................................................................................................................................... 12 Layout ........................................................................................................................................... 13 La classe Resource ...................................................................................................................... 14

Il file Resources / values / strings.xml ............................................................................................... 14 Il file AndroidManifest.xml ................................................................................................................. 14 Lancio dell’applicazione .................................................................................................................... 16 Widget e View .................................................................................................................................. 16

Accesso ai controlli : La proprietà numerica id ............................................................................. 16 La Gestione degli eventi ................................................................................................................... 17

1° soluzione (direi la più comoda) ................................................................................................. 17 2° soluzione .................................................................................................................................. 17 3° Soluzione Associazione di una procedura di evento tramite il designer .................................... 17 Associazione di uno stesso evento a più controlli ......................................................................... 18 L’evento onTouch ......................................................................................................................... 18

Il concetto di Context ........................................................................................................................ 19 Le finestre di pop up : i Toast ........................................................................................................... 19 AlertDialog ........................................................................................................................................ 20

Utilizzo di un unico Listener .......................................................................................................... 21 Input Dialog ...................................................................................................................................... 21

Controlli e Proprietà ............................................................................................................................. 22 La scalatura delle immagini PX vs DP ................................................................................................ 22

Istruzioni per la converione da px a dp .......................................................................................... 23 La casella di testo : il widget EditText .............................................................................................. 23

La gestione delle immagini : il widget ImageView ......................................................................... 24 Il metodo Resources.GetIdentifier() .............................................................................................. 24

Gestione dello schermo .................................................................................................................... 25 Rotazione dello schermo............................................................................................................... 25 Lettura delle Dimensioni dello schermo ......................................................................................... 25

Check Box e Radio Button ............................................................................................................... 25 Impostazione delle proprietà tramite designer .................................................................................. 26 Impostazione delle proprietà tramite codice ...................................................................................... 27

Le proprietà di tipo layout .............................................................................................................. 27 Creazione Dinamica dei controlli .......................................................................................................... 28

Note sulla gestione dell’Id ................................................................................................................. 28

Page 2: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 2

Assegnazione dinamica dell’ID tramite codice .............................................................................. 29 Layout .............................................................................................................................................. 30

LinearLayout ................................................................................................................................. 30 RelativeLayout .............................................................................................................................. 30 TableLayout .................................................................................................................................. 31 FrameLayout ................................................................................................................................. 31 ConstraintLayout ........................................................................................................................... 31 Associazione di un layout ad una Activity ...................................................................................... 32 Dimensioni dell’Area client di un layout ......................................................................................... 32 Navigazione all’interno di un layout ............................................................................................... 32 Cancellazione di elementi ............................................................................................................. 32 Scroll di un Layout ........................................................................................................................ 32

INTENT ................................................................................................................................................ 33 Intent Espliciti ed Impliciti .............................................................................................................. 33

Utilizzo degli intent impliciti ............................................................................................................... 34 Manipolazione dell’intent dell’ AndroidManifest.xml con Xamarin ..................................................... 35

Metodi per l’invio di un intent al Sistema Operativo ....................................................................... 36 Richiamo di una Activity mediante un intent esplicito ........................................................................ 36

Come riportare una Activity in primo piano .................................................................................... 36 Ciclo di vita di una Activity ................................................................................................................ 37

Il metodo Finish() ed il pulsante BACK ......................................................................................... 38 Passaggio di parametri ad una Activity ............................................................................................. 38

Lettura dei parametri in Activity2 ................................................................................................... 38 Restituzione di un risultato ............................................................................................................... 39

Lettura del risultato da parte di Activity1 ........................................................................................ 39 Gestione dei thread .......................................................................................................................... 40

Utilizzo di un thread generico ........................................................................................................ 40 Sleep di un thread ......................................................................................................................... 40

La classe Action ............................................................................................................................... 41 Menù .................................................................................................................................................... 41

OptionsMenu .................................................................................................................................... 41 Evento OnCreateOptionMenu ....................................................................................................... 41 Aggiunta di nuove voci tramite il metodo add() .............................................................................. 42 Accesso all’item e relativi metodi .................................................................................................. 42 Aggiunta di un Submenu ............................................................................................................... 42 Evento OnOptionsItemSelected di risposta al click sulle voci ................................................. 43

Creazione statica di un OptionMenu tramite file xml ......................................................................... 43 Accesso al file di risorsa tramite l’inflater ....................................................................................... 44

ContextMenu .................................................................................................................................... 45 Evento OnCreateOptionMenu ................................................................................................... 45 Il metodo OpenContextMenu(myControl) ...................................................................................... 46

Android Device Monitor .................................................................................................................... 46 Finestra File Explorer .................................................................................................................... 46

Le aree di memoria di una app ............................................................................................................. 46 Accesso ai files memorizzati nel Internal Storage ............................................................................. 47 Accesso ai files memorizzati nell’External Storage ........................................................................... 47

Shared Preferences ............................................................................................................................. 48 ListView e ArrayAdapter ....................................................................................................................... 49

ArrayAdapter .................................................................................................................................... 49 ListView ............................................................................................................................................ 49

Evento OnItemClick ...................................................................................................................... 50 Scroll del List View ........................................................................................................................ 50

Spinner ............................................................................................................................................. 50 GridView........................................................................................................................................... 50 Creazione di un Adapter personalizzato ........................................................................................... 50

Page 3: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 3

Step 1 Definizione di un rowlayout personalizzato ........................................................................ 51 Step 2 Definizione di un Adapter personalizzato per la gestione dei dati ....................................... 51 Pulsanti interni all’Adapter ............................................................................................................. 52

Accesso ad un web service HTTP ....................................................................................................... 53 La classe astratta AsynkTask ....................................................................................................... 53 Metodi della classe AsyncTask ..................................................................................................... 53 Dichiarazione di una classe che eredita da AsyncTask ................................................................. 54 MainActivity: Istanza della classe ed invo della richiesta ............................................................... 54 Nota sull’indirizzo IP ...................................................................................................................... 55 Oggetti per l’invio di una richiesta HTTP ....................................................................................... 55 Soluzione 2: La classe HttpURLConnection (più semplice) .......................................................... 57

Gestione di uno stream jSon ................................................................................................................ 59 Richiesta di una immagine al server ................................................................................................. 60

Page 4: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 4

Android SDK Il SO Android usa un kernel Linux dalla versione 2.6 in avanti (dunque con supporto ai multithread). Sopra c’è Android Run Time (ART) basato sulle Librerie Java Core che sono una versione ridotta delle librerie SE. Lo pseudo codice prodotto dai compilatori android viene tradotto a run time in un eseguibile vero e proprio mediante un compilatore Just In Time che legge lo pseudocodice e crea un eseguibile vero e proprio. Android è stato originariamente sviluppato da una piccola azienda, la Android Inc, ma nel 2005 Google ne acquistò i diritti e decise di rilasciare Android in modalità open source, il che significa che chiunque voglia utilizzare tale sistema può farlo semplicemente scaricando l’intero codice sorgente. Tuttavia i produttori di hardware possono aggiungere le proprie estensioni al sistema e personalizzare Android per differenziare i propri prodotti dagli altri Le applicazioni per Android sono distribuite mediante files .APK (Android Package) che sono files compressi in un formato simile al JAR. I file .apk possono essere aperti e ispezionati utilizzando applicativi comuni come 7-Zip, Winzip Winrar o X-Plore (in smartphone Android o Symbian). La presentazione ufficiale della prima versione del "robottino verde" avvenne il 5 novembre 2007 da parte della neonata OHA (Open Handset Alliance), un consorzio di aziende del settore Hi Tech che include Google, produttori di smartphone come HTC e Samsung, operatori di telefonia mobile come Sprint Nextel e T-Mobile, e produttori di microprocessori come Qualcomm e Texas Instruments. Oggi copre il 78 % del mercato nella vendita di smartphone / tablet:

Uno dei fattori principali che determinano il successo (o meno) di una piattaforma per dispositivi mobili è la varietà di applicazioni che essa mette a disposizione degli utenti. A partire dalla fine del 2008, Google ha messo a disposizione degli utenti l’Android Market (oggi Google Play), un’applicazione on-line attraverso la quale gli utenti possono installare applicazioni aggiuntive sui propri dispositivi. Su Google Play sono disponibili sia applicazioni gratuite che a pagamento.

Page 5: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 5

Ogni aggiornamento o release, similmente a quanto accade per molte versioni di Linux, segue un ordine alfabetico e una precisa convenzione per i nomi, che in questo caso sono quelli di dolci:

versione 1.5 Cupcake (30 aprile 2009 – API Level 3) versione 1.6 Donut (30 aprile 2009 – API Level 4) versione 2.0 Eclair (26 ottobre 2009 – API Level 5) versione 2.2 Froyo (20 maggio 2010 – API Level 8) versione 2.3 Gingerbread (6 dicembre 2010 – API Level 9) versione 3.0 Honeycomb (22 febbraio 2011 – API Level 11) versione 4.0 Ice Cream Sandwich (19 ottobre 2011 – API Level 14) versione 4.1 Jelly Bean (9 luglio 2012 – API Level 16) versione 4.2 Jelly Bean (13 novembre 2012 – API Level 17) versione 4.3 Jelly Bean (24 luglio 2013 – API Level 18) versione 4.4 Kit Kat n seguito ad un accordo con la Nestlé (31 ottobre 2013 – API Level 19) versione 5.0 Lollipop lanciata il 3 novembre 2014 (API Level 21) versione 5.1 Lollipop lanciata il 9 marzo 2015 (API Level 22) versione 6.0 Marshmallow lanciata il 5 ottobre 2015 (API Level 23) versione 7.0 Nougat lanciata il 22 agosto 2016 (API Level 24) versione 7.1 Nougat lanciata il 20 ottobre 2016 (API Level 25) versione 8.0 Oreo lanciata il 21 agosto 2017 (API Level 26) versione 8.1 Oreo lanciata il 25 ottobre 2017 (API Level 27) versione 9.0 Pie lanciata il 6 agosto 2018 (API Level 28) Ambiente di sviluppo

Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK che include: gli strumenti di sviluppo, le librerie, un emulatore del dispositivo, la documentazione (in inglese), alcuni progetti di esempio, tutorial e altro. E’ disponibile per:

qualsiasi piattaforma Linux,

qualsiasi piattaforma x86 compatibile che usi un sistema operativo Windows (da XP in avanti)

Mac OS X, dalla versione 10.4.8,

L'IDE ufficialmente supportato per lo sviluppo di applicazioni per Android è Eclipse, per il quale è fornito un SDK ufficiale denominato ADT (Android Development Tools), che contiene tutte le librerie necessarie allo sviluppo.

Versioni diverse dell’SDK possono convivere sulla stessa macchina, Nelle ultime versioni sono disponibili API per Google Maps, Facebook, mixPanel (statistiche) Compilzione

Java Source Compilatore javac Class files dx legge i class files e le risorse e genera i .dex files (Dalvik EXecutable, dove Dalvik era la vecchia Android Virtual

Machine oggi sostituita da ART) jar (compattatore) legge i files dex e genera un file finale .apk che è il file tipico da installare su un sistema Android

Page 6: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 6

L’APK viene invito direttamente all’emulatore o al dispositivo vero e proprio.

Un file APK (Android Package) è un archivio che contiene le seguenti cartelle:

RES (risorse: costanti, form, immagini)

META-INF contenente i certificati (a chiave pubblica) che garantiscono riguardo alla bontà della app che si sta scaricando.

ed i seguenti files:

AndroidManifest.xml ( file xml che descrive l’applicazione)

class.dex che è lo pseudo eseguibile vero e proprio che verrà eseguito dall’Android Run Time

A run time viene generato un processo diverso per ogni applicazione da eseguire.

Programmazione in Android Studio

Per ciò che riguarda la programmazione in Android Studio è necessario installare Java e Android Studio che include anche l’SDK per gestire sia le versioni dei pacchetti sia gli emulatori.

Programmazione in Visual Studio C# con Xamarin

Per la programmazione con Visual studio facciamo riferimento alla versione 2017 – 15.9.6, ma che cos’è?

Nel Maggio 2011 nasce Xamarin, una società informatica creata da N. Friedman e M. de Icaza, quest’ultimo noto per aver coordinato la realizzazione di Mono (framework open source per l’implementazione del .NET Framework di Microsoft su Linux). L’idea di Xamarin è di offrire agli sviluppatori un modo semplice e veloce per creare app cross-platform basate su un unico linguaggio orientato agli oggetti attraverso ambienti di sviluppo prestanti. Per raggiungere tale obiettivo, è stato creato il framework Xamarin basato su Mono e quindi C#. Gli sviluppatori possono usare gli strumenti Xamarin per scrivere applicazioni native Android, iOS e Windows con interfacce utenti native e condividere il codice su diverse piattaforme. Nel febbraio del 2016, Microsoft ha acquistato l'azienda, e dopo qualche mese, ha reso i prodotti Xamarin Studio gratuiti per sviluppatori e studenti. Componenti di Xamarin

Page 7: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 7

Xamarin si compone di tre componenti principali:

Xamarin.Android Basato su Mono, permette lo sviluppo di app Android tramite un wrapping delle API native in C#

Xamarin.iOS

Basato sulla libreria proprietaria MonoTouch, offre pieno supporto allo sviluppo di app iOS tramite un wrapping delle API native in C#

Xamarin.Forms Si pone al di sopra dei precedenti componenti e permette la piena condivisione del codice

Grazie a queste componenti è possibile gestire in C# tutte le caratteristiche di Android, iOS e Windows Phone, dall’interfaccia utente alle risorse hardware del dispositivo. Tale suddivisione permette di gestire la UI attraverso:

elementi tipici delle singole piattaforme (grazie al binding con le SDK native);

elementi definiti in Xamarin.Forms nel caso di app cross-platform in cui è necessario mostrare agli utenti una UI più familiare.

Uno dei principali benefici di Xamarin, infatti, è la possibilità di sviluppare contemporaneamente un’app per diverse piattaforme grazie a Xamarin.Forms. Una soluzione cross-platform basata su Xamarin.Forms offre una architettura a tre strati, partendo dal basso:

Core Library Offre la logica dell’applicazione e di accesso ai dati definita in C#

Cross-Platform UI Layer

È lo strato contenente tutta la UI realizzata, ad esempio, con Xamarin.Forms definita in C#

Platform-Specific Inizialization Code

Ha un piccola porzione di codice in C# nei progetti di ogni piattaforma ed è necessario per inizializzare ed eseguire l’app su ogni OS nativo

Page 8: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 8

Requisiti

I requisiti di Xamarin sono gli stessi previsti per l’utilizzo delle SDK di Android, data la natura del framework che si basa su queste. Il sistema operativo per sviluppare può essere scelto tra Windows e Mac OS X, escludendo almeno per ora gli utenti Linux. Xamarin offre la possibilità di usare due diversi IDE per lo sviluppo di app native, cross-platform e desktop:

IDE Descrizione

Xamarin

Studio

Realizzato da Xamarin, permette la creazione di app iOS, Android e Mac e include

l’integrazione con le SDK native, strumenti di debug e diverse funzionalità per la

scrittura di codice.

Visual

Studio (VS)

Offre un ambiente intuitivo e facilmente estendibile. Nel 2015, è stata rilasciata una

versione gratuita, Visual Studio Community, con l’occorrente per la creazione di app

moderne mobile, desktop e web.

Nonostante la possibilità di sviluppare app cross-platform e native, ci si trova a dover affrontare i limiti imposti dalle piattaforme mobile. Di seguito è riportata una tabella che mostra i limiti delle due IDE per i due sistemi operativi considerati.

Installazione con Visual Studio 2017

Xamarin può essere installato durante durante una nuova installazione di Visual Studio 2017 seguendo alcuni accorgimenti:

Scaricare Visual Studio 2017 Comunity, Professional o Enterprise

Avviare l’installazione

Selezionare Mobile development with .NET

Page 9: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 9

Per ciò che riguarda il pannello sui Dettagli installazione possiamo lasciare le impostazioni di default

Quindi fare click su Install

Al termine dell’installazione fare click su Avvia Aggiunta di Xamarin ad una versione di Visual Studio 2017 già installata Eseguire nuovamente il programma di installazione di Visual Studio e seguire i passi elencati sopra per aggiungere Xamarin. Per verificare se Xamarin è stato installato si può andare a fare click su ? per verificare se compare:

E’ anche possibile cliccando su “Informazioni su Microsoft Visual Studio” per verificare se è presente Xamarin:

Configurazione Xamarin

L’installazione di Xamarin consente di iniziare a scrivere il codice per le app, ma potrebbero essere necessarie operazioni di configurazione aggiuntive. Per ciò che riguarda Android: Xamarin.Android usa Java Development Kit (JDK) e Android SDK per compilare le app. Durante l'installazione, il programma di installazione di Visual Studio inserisce questi strumenti nei percorsi predefiniti e configura l'ambiente di sviluppo con la configurazione del percorso appropriata. È possibile visualizzare e modificare questi percorsi facendo clic su Strumenti > Opzioni > Xamarin > Impostazioni Android:

Page 10: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 10

Per poter sviluppare con le API 24 o superiori è necessaria la JDK 8 (che comunque supporta anche le API a livello inferiore). Se si usa la JDK 7 si potrà invece sviluppare a livello API 23 o un livello precedente. Importante Xamarin.Android non supporta JDK 9.

Android SDK Manager

E’ possibile installare più varsioni di API Android per poter andare a testare l’App su ognuna di queste. Ciò può essere fatto tramite SDK Manager che viene installato assieme a Xamarin. Lo trovate facendo click su Strumenti > Android > Android SDK Manager:

Per impostazione predefinita, Visual Studio installa Android SDK e strumenti Android:

Tramite questo strumento potete gestire tutte le vostre versioni Android.

Page 11: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 11

Emulatore Android

L'emulatore Android può essere utile per sviluppare e testare un'app Xamarin.Android. È ad esempio possibile che un dispositivo fisico, ad esempio un tablet, non sia immediatamente disponibile durante lo sviluppo e quindi può essere comodo andarlo a simulare tramite l’emulatore. L'emulazione di un dispositivo Android in un computer richiede i componenti seguenti:

Emulatore Android di Google: si tratta di un emulatore basato su QEMU che crea un dispositivo virtualizzato eseguito nella workstation dello sviluppatore.

Immagine dell'emulatore: un'immagine dell'emulatore è un modello o una specifica dell'hardware e del sistema operativo che deve essere virtualizzato. Ad esempio, un'immagine dell'emulatore identificherà i requisiti hardware per Nexus 5X che esegue Android 7.0 con Google Play Services installato. Un'altra immagine dell'emulatore potrebbe specificare una tablet da 10" che esegue Android 6.0.

Dispositivo virtuale Android (AVD) un dispositivo virtuale Android è un dispositivo Android emulato creato da un'immagine dell'emulatore. Durante l'esecuzione e il test di app Android, Xamarin.Android avvierà l'emulatore Android, avviano un AVD specifico, installerà il pacchetto APK ed eseguirà l'app.

Grazie a immagini dell'emulatore speciali ottimizzate per l'architettura x86 e a una delle due tecnologie di virtualizzazione, è possibile ottenere un miglioramento significativo delle prestazioni durante lo sviluppo di computer x86:

1. Microsoft Hyper-V–: disponibile in computer che eseguono l'aggiornamento di aprile 2018 di Windows 10 o versioni successive.

2. Hardware Accelerated Execution Manager (HAXM) – di Intel: disponibile in computer x86 che eseguono OS X, macOS o versione precedente di Windows.

Dispositivo fisico Android

Se si dispone di un dispositivo Android fisico da usare per il test, lo si può configurare per usarlo per il processo di sviluppo. Ne gioverà sicuramente la velocità di esecuzione della macchina e dell’emulatore.

Creazione di applicazioni tramite Visual Studio

Una applicazione Android è identificata da un package univoco. packege è sinonimo di namespace. Visual Studio definisce automaticamente il package come package="namespace.assemblyName"

Sul nome del package ci deve essere almeno un puntino. Una applicazione Android è articolata nelle seguenti sezioni:

Properties – AndroidManifest e AssemblyInfo

Riferimenti – Riferimenti alle risorse incluse nel progetto

Assets – In questa caretella andranno inseriti i file che non vogliamo che vengano toccati/elaborati da

Android (Rimarranno così inalterati) bin – compilati (APK e DEX)

Resources (layout, values, drawable, animazioni)

Una applicazione può utilizzare quattro tipi di componenti :

Activity - è il codice che gestisce un layout (form)

Service - sono eseguiti in background e non hanno interfaccia grafica Broadcast Receiver

Content Provider (fornitore di contenuti)

Page 12: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 12

I servizi non sono in grado di inviare nulla a monitor I servizi al massimo possono scrivere sul notification Manager

Le activity NON possono accedere al notification Manager Una applicazione può avere più activity e più services Una app non può lanciare un’altra app, ma può lanciare una activity di un’altra app

Il primo esercizio

Iniziamo un nuovo progetto Android:

Selezionare Android e poi App Android

Inserire il nome del progetto e il nome della soluzione e premero OK

Nella finestra successiva selezionare App vuota e come versione minima va benissimo quella proposta la 5.0

Activity

Un'activity rappesenta una classe che consente di interagire con gli elementi di un layout. :

Una Empty Activity è una classe che estende (cioè eredita da) AppCompatActivity, che NON è una classe astratta, ma della quale è richiesto di ridefinire il metodo onCreate.

Una Activity vuota presenta inizialmente il seguente codice:

public class MainActivity : AppCompatActivity

{

protected override void OnCreate(Bundle savedInstanceState)

{

base.OnCreate(savedInstanceState);

// Set our view from the "main" layout resource

SetContentView(Resource.Layout.activity_main);

}

}

Il metodo onCreate viene richiamato al momento dell’avvio dell’Activity. All'interno di questo metodo occorre inserire tutto il codice riguardante la struttura della activity.

Page 13: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 13

savedInstanceState è lo stato dell’activity salvato su disco in un’area di sistema. Lo stato

viene automaticamente iniettato a onCreate() al momento del lancio

Per prima cosa onCreate() deve richiamare il metodo onCreate() della superClasse

setContentView(Resource.Layout.activity_main) è un metodo dell’Activity che

consente di associare all’Activity il Layout contenuto nel file activity_main.axml della cartella Resources/layout del progetto corrente. Ogni Activity di solito ha assegnato un Layout.

Layout

Resources / layout / activity_main.axml

activity_main.xml sostanzialmente rappresenta la form principale del progetto. Con doppio click si accede al designer costituito da due finestre :

Design contiene il layout grafico della form completabile tramite trascinamento

Text contiene il codice xml relativo alla creazione dei controlli posizionati sulla form.

Si può indifferentemente scrivere codice oppure trascinare gli oggetto sul designer. All’interno della form occorre impostare un oggetto layout. I Layouts molto simili a quelli usati in Android Studio e in Java all’interno dei Panels. Per default viene impostato un Relative Layout che consente di posizionare i controlli in modo realito uno rispetto all’altro.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <TextureView android:layout_width="wrap_content" android:layout_height="wrap_content" android:minWidth="25px" android:minHeight="25px" android:id="@+id/textureView1" /> </RelativeLayout>

All’interno del contesto Layout si possono posizionare dei Widget che sono i controlli di interazione con l’utente. Provare ad utilizzare i vari tipi di Label (Plain Text View, Large Text, etc.).

Nelle prime due linee viene impostata la larghezza e l'altezza della Casella di Testo. Il valore wrap_content ha l'effetto di estendere l'elemento per una larghezza ed un'altezza tale da

contenere il testo inserito.

Page 14: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 14

La classe Resource

Il file Resources / values / strings.xml

Questo file consente di definire delle costanti di parametrizzazione dell’applicazione, nel senso che l’applicazione può usare queste stringhe in qualsiasi segmento di codice. Esempio di file strings.xml

<resources>

<string name="app_name">App2</string>

<string name="action_settings">Settings</string>

<string name="titolo">Home page</string>

</resources>

La stringa app_name può essere modifica a piacere e consente di cambiare rapidamente il nome

visualizzato sulla barra superiore della app

Utilizzo della stringa titolo all’interno del layout

<TextView android:text = "@string/titolo" />

Utilizzo della stringa titolo all’interno del codice della Activity

Per leggere da codice le stringhe memorizzate all’interno del file strings.xml occorre utilizzare il metodo this.getString()

txt.Text = "Hello " + this.GetText(Resource.String.action_settings);

Il file AndroidManifest.xml

Il file Manifest.xml è un file in cui devono essere registrati tutti i componenti appartenenti al progetto. E’ l’equivalente del file di Progetto di C#. Ogni activity deve essere registrata nel file Manifest. Nel file AndroidManifest.xml al momento della creazione del progetto troviamo:

E’ una classe base autogenerata dal framework che serve a gestire tutte le risorse memorizzate dentro res (layout, etc).

All’interno del file Resource il compilatore memorizza un puntatore numerico esadecimale per ogni elemento contenuto all’interno del Layout.

Visibile in Project Files -->

Page 15: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 15

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

android:versionCode="1"

android:versionName="1.0"

package="App2.App2">

<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />

<application android:allowBackup="true"

android:icon="@mipmap/ic_launcher"

android:label="@string/app_name"

android:roundIcon="@mipmap/ic_launcher_round"

android:supportsRtl="true"

android:theme="@style/AppTheme">

</application>

</manifest>

il file manifest contiene informazioni dettagliate riguardo all’applicazione. Definisce :

il nome del package,

icon = icona da utilizzare per rappresentare l’applicazione sul dispositivo.

label = Nome identificativo dell’applicazione.

<application>

<activity> Per ciò che riguarda le informazioni dell’activity Visual Studio, tramite un’apposita sintassi, le aggiungere in automatico al momento della compilazione: [Activity (Name="mono.samples.HelloApp",

Label="Hello! Wie gehts!",

MainLauncher=true,

ConfigurationChanges=ConfigChanges.Mcc|ConfigChanges.Mnc,

LaunchMode=LaunchMode.Multiple,

ScreenOrientation=ScreenOrientation.Unspecified,

WindowSoftInputMode=SoftInput.StateUnspecified|

SoftInput.AdjustUnspecified)]

class MyActivity : Activity {

}

Questo andrà a generare nel manifest le seguenti righe XML: <activity android:configChanges="mcc|mnc"

android:label="Hello! Wie gehts!"

android:launchMode="standard"

android:name="mono.samples.HelloApp"

android:screenOrientation="unspecified"

android:windowSoftInputMode="stateUnspecified|

adjustUnspecified">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

Per ogni Activity vengono memorizzati il name e, all’interno dell’intent-filter, le

caratteristiche dell’Activity :

Page 16: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 16

- I valori MAIN LAUNCHER indicano che si tratta di una Activity che può essere lanciata

direttamente da SO. Tutte le Activity di questo tipo verranno visualizzate sul desktop del dispositivo.

- Se invece l’activity presenta il valore category = DEFAULT significa che si tratta di una

Activity secondaria richiamabile soltanto da un’altra Activity. In questo caso all’interno di action è possibile specificare un nome che potrà essere utilzzato per avviare l’activity. Nel

caso di Activity di tipo DEFAULT la sezione <intent-filter> può anche essere omessa.

Lancio dell’applicazione

Pulsantino play in alto

Prima di lanciare l’applicazione, occorre verificare che l’emulatore sia avviato o che il dispositivo fisico sia collegato. L’emulatore può essere avviato andando a cliccare sul pulsante in alto “Android Device Manager”.

Widget e View

Ogni elemento appartenente al package Android.Widget ha come superclasse la classe View che è

un astrazione di ciò che vedrà l'utente sullo schermo. Per creare un componente personalizzato è sufficiente creare una classe che estenda la classe View o una sua sotto-classe.

Accesso ai controlli : La proprietà numerica id

Ogni widget deve avere come identificativo un nome che necessariamente deve iniziare con ilprefisso @+id/ Se lo si omette le associazioni non vengono eseguite correttamente.

Questo prefisso viene impostato in automatico nel momento in cui si trascina un widget sul layout. Bisogna fare attenzione, perché in alcuni casi il designer lo crea senza il + e quindi poi non funziona (basta aggiungerlo a mano nell’xml per far funzionare tutto)

Es: @+id/button1

Per accedere ai widget dall’interno dell’Activity si utilizza il metodo FindViewById (View = Controllo)

Button btn = FindViewById(Resource.Id.button1) as Button;

TextView txt = FindViewById(Resource.Id.textureView1) as TextView;

Resource.Id.button1 è in realtà una costante numerica di tipo int definita dal compilatore all’interno

del file Resource Due widget anche appartenenti a Layout differenti NON possono avere lo stesso nome. I nomi devono cioè essere univoci a livello dell’intera applicazione.

FindViewById è un metodo disponibile all’interno di :

una Activity

un oggetto di tipo xmlLayout, il cui puntatore può essere recuperato a partire dall’ID statico facedo uso di un oggetto denominato Inflater

In entrambi i casi, pur essendo l’ID dei controlli univoco a livello di applicazione, FindViewById consente di acceddere soltanto ai controlli posizionati sul xmlLayout al quale si riferisce.

L’evento onCreate, oltre alle inizializzazioni, serve a definire delle procedure di evento che verranno eseguite in corrispondenza del verificarsi dell’evento. Quando la procedura termina le variabili locali vengono rimosse, per cui non sono più accessibili al momento dell’evento.

Page 17: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 17

La Gestione degli eventi

Gli eventi sono gestiti tramite appositi oggetti detti listener.

1° soluzione (direi la più comoda)

Button btn1 = (Button)FindViewById(Resource.Id.btnMessaggio1);

btn1.Click += (sender, e) => {

};

In questo modo viene aggiunto all’evento Click un metodo anonimo al quale vengono passati due parametri: il sender che rappresenta il controllo che ha generato l’evento ed e un EventArgs che non fornisce alcuna informazione aggiuntiva. 2° soluzione

Si va a far si che la MainActivity implementi l’interfaccia View.IOnClickListener. In questo modo è

possibile ridefinire l’evento onClick direttamente all’interno della classe corrente: public void OnClick(View v)

{

if (v.Id == Resource.Id.btnPremi)

{

Toast.MakeText(this, "Premuto!", ToastLength.Long).Show();

}

}

Il metodo OnClick riceve come unico parametro la View (il controllo) che ha generato l’evento.

Per associare un listener di evento ad un controllo occorre accedere al controlo tramite il metodo FindViewById e poi utilizare il metodo Set seguito dal nome della classe di ascolto: SetOnClickListener :

Button btn1=(Button) findViewById(R.id.btnPremi);

btn1.setOnClickListener(myListener);

Button btn3 = (Button)FindViewById(Resource.Id.btnPremi);

btn3.SetOnClickListener(this);

3° Soluzione Associazione di una procedura di evento tramite il designer

Nel caso del solo evento click, è sufficiente, fuori dal metodo onCreate(), definire una generica procedura con firma adeguata e poi assegnarla all’evento direttamente tramite Designer cercando nella finestra delle Properties l’evento On Click e scrivendo il nome del metodo senza parametri.

[Java.Interop.Export("ClickDue")]

public void ClickDue(View v)

{

}

Attenzione che :

Il metodo deve essere dichiarato public.

Questa tecnica funziona esclusivamente per l’evento onClick, per il quale è stata definita una property aggiuntiva che consente di memorizzare il puntatore alla classe di gestione dell’evento

Bisogna utilizzare la dicitura Java.Interop.Export("ClickDue") dove si va a rendere

visibile il metodo col nome assegnato

Page 18: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 18

Bisogna Aggiungere il riferimento a Mono.Android.Export Associazione di uno stesso evento a più controlli

La seconda e la terza soluzione hanno il vantaggio di poter associare lo stesso listener a più controlli. All’interno del listener si può utilizzare uno switch per individuare il controllo che ha scatenato l’evento:

public void OnClick(View v)

{

switch (v.Id)

{

case Resource.Id.btnPremi:

break;

case Resource.Id.btnMessaggio1:

break;

default:

break;

}

}

btn1.SetOnClickListener(this);

btn2.SetOnClickListener(this);

L’evento onTouch

Al posto dell’evento onClick è possibile utilizzare l’evento onTouch che presenta la seguente sintassi:

btn.Touch += (sender, e) =>

{

// Evento non ancora gestito

var handled = false;

if (e.Event.Action == MotionEventActions.Down)

{

// Evento gestito

handled = true;

((Button)sender).Text = "Premuto";

}

else if (e.Event.Action == MotionEventActions.Up)

{

// Evento gestito

handled = true;

((Button)sender).Text = "Rilasciato";

}

// Informo il sistema se l'evento è stato gestito o meno

e.Handled = handled;

};

Il primo parametro rappresenta il controllo che ha generato l’evento

Il secondo parametro rappresenta l’azione specifica legata al Touch (ACTION_DOWN, ACTION_UP, ACTION_MOVE, etc.)

L’evento onTouch risulta sprattuto utile quando si vogliono andare a gestire le gestures

Page 19: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 19

Il concetto di Context

La classe Context è la classe base da cui, mediante più passaggi, ereditano le classi Activity.

Rappresenta una specie di interfaccia che consente all’Activity corrente di accedere a risorse e informazioni specifiche relative all’applicazione.

Context con = Application.Context;

Mediante il context è possibile accedere ad un ampio insieme di caratteristiche e servizi a

disposizione dell’applicazione. Il Context corrente viene utilizzato per :

accedere alle stringhe costanti memorizzate in strings.xml string s=con.GetString(Resource.String.app_name);

accedere alle eventuali variabili condivise dell’applicazione:: ISharedPreferences pref = con.GetSharedPreferences("spref",

FileCreationMode.Private);

quando si creano nuovi oggetti, per fare in modo che il nuovo oggetto possa anche lui accedere a risorse e informazioni relative all’applicazione, occorre passare all’oggetto il context corrente: TextView lbl = new TextView(context);

Visto che la classe Activity deriva dalla classe Context all’interno del codice della classe Activity il

this rappresenta il Context dell’applicazione.

Per accedere al Context, a seconda dei casi, si può utilizzare una delle seguenti sintassi:

this // istanza corrente

MyActivity.this; // MyActivity. this è una proprietà che punta all’istanza corrente

v.Context; // v è il puntatore ricevuto come parametro dal gestore di evento

Application.Context; // disponibile in ogni situazione. Non sempre funziona. Non

segnala errori di compilazione ma poi provoca Run Time Error

Le finestre di pop up : i Toast

Le finestre di pop up sono le cosiddette shallow window, cioè le finestre che appaiono / scompaiono con una durata temporanea paragonabile ad una notifica. Scopo di questo widget è quello di notificare all'utente un messaggio del tipo "salvataggio effettuato" oppure "operazione ok" in seguito a qualche operazione compiuta dall'utente .

Rispetto alle Alert Dialog il Toast è molto più semplice, non ha pulsanti di interazione e, dopo un breve tempo, scompare da solo senza che l’utente debba eseguire un click.

Per la costruzione del Toast di fa uso del metodo statico Toast.makeText che presenta 3 parametri che

sono :

1. Il Context dell’applicazione nel quale applicare il toast. 2. Il messaggio da visualizzare 3. La durata della visualizzazione (LONG oppure SHORT)

Toast t = Toast.MakeText(this, "Ciao", ToastLength.Long);

t.Show();

E’ anche possibile aggiungere il testo in un secondo momento, dopo aver istanziato l’oggetto:

Toast t = Toast.MakeText(this, "", ToastLength.Long);

t.SetText("Ciao a tutti!!!");

Page 20: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 20

t.Show();

Utilizzo del toast per la visualizzazione di una immagine

Un toast non può visualizzare contemporaneamente Testo e Immagine. O il testo, o l’immagine. Nel caso si voglia visualizzare una immagine, occorre per prima cosa caricare l’immagine da utilizzare. Dopo di che occorre associare l’immagine al toast trmite la property t.View

Toast t = Toast.MakeText(this,"",ToastLength.Long);

ImageView im = new ImageView(this);

im.SetImageResource(Resource.Mipmap.ic_launcher);

t.View = im;

t.Show();

AlertDialog

Widget utilizzato tipicamente per richiedere una richiesta di conferma da parte dell'utente per una qualche operazione. Per esempio un'applicazione che richiede una connessione ad Internet, potrebbe mostrare un'AlertDialog all'utente nel caso in cui il dispositivo non si riesca a collegarsi ad Internet.

AlertDialog.Builder builder = new AlertDialog.Builder(this);

builder.setTitle("AlertDialog");

builder.setMessage("E' stato premuto Pulsante 3");

builder.setIcon(Resource.Mipmap.ic_launcher);

Aggiunta dei pulsanti di dialogo

Le dialog vengono automaticamente chiuse in corrispondenza del click su uno dei pulsanti di dialogo. Se non vengono inseriti pulsanti di dialogo, per chiudere la AlertDialog occorre clickare nell’area dell’Activity. I pulsanti di dialogo utilizzabili sono 3:

PositiveButton posizionato nella parte destra della finestra

NegativeButton posizionato nella parte centrale della finestra

NeutralButton posizionato nella parte sinistra della finestra

builder.setPositiveButton("OK", (senderAlert, args) =>

{

this.Finish();

});

builder.setNegativeButton("Cancel", (senderAlert, args) =>

{

Toast.MakeText(this, "Chiusira cancellata",

ToastLength.Short).Show();

});

builder.setNeutralButton("Annulla", (senderAlert, args) =>

{

Toast.MakeText(this, "Chiusira annullata",

ToastLength.Short).Show();

});

Il primo parametro indica il testo da visualizzare all’interno del pulsante

Il secondo parametro indica un oggetto Listener da gestire in modo simile a quello del click di un bottone.

Il metodo dialog.cancel() chiude la finestra corrente (che però in realtà si chiude da sola)

builder.setCancelable(true/false); il false ha l'effetto di disabilitare il tasto back del

telefono e dunque l'utente dovrà necessariamente cliccare su uno dei bottoni per chiudere la Dialog che quindi diventa modale.

Page 21: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 21

al termine ricordarsi di inserire il builder.show() per visualizzare l’alert.

Utilizzo di un unico Listener

L’evento onClick dell’ DialogInterface.OnClickListener si aspetta due parametri:

1. un oggetto di tipo AlertDialog che indica quale dialog ha generato l'attivazione del listener. Attenzione AlertDialog, non Builder. Occorre pertanto utilizzare il builder.create().

2. un int che identifica il bottone premuto all’interno della dialog

Questi due parametri consentono di realizzare un unico Listener per tutte le AlertDialog dell’applicazione con i relativi pulsanti. Ciò si realizza semplicemente eseguendo un primo switch sul parametro dialog (identificando quale AlertDialog ha attivato il listener) con all’interno un altro switch per capire quale bottone, relativo alla AlertDialog presa in esame, è stato cliccato.

Eempio:

public void onClick(DialogInterface dialog, int which) {

String text = "";

if (dialog == dlg2) {

switch (which) {

case DialogInterface.BUTTON_POSITIVE: // -1

text = "OK";

case DialogInterface.BUTTON_NEGATIVE: // -2

text = "No";

case DialogInterface.BUTTON_NEUTRAL: // -3

text = "Cancel";

}

Toast.makeText(this, text, Toast.LENGTH_LONG).show();

}

}

Input Dialog

Per trasformare una AlertDialog in InputDialog è sufficiente aggiungere una casella di input

all’interno della Dialog stessa.

EditText input = new EditText(this);

input.SetRawInputType(Android.Text.InputTypes.ClassText);

dlg.SetView(input);

dlg.SetPositiveButton("OK", (senderAlert, args) =>

{

this.Finish();

});

dlg.SetNegativeButton("Cancel", (senderAlert, args) =>

{

Toast.MakeText(this, input.Text+ " - Chiusira annullata",

ToastLength.Short).Show();

});

Page 22: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 22

Controlli e Proprietà

La scalatura delle immagini PX vs DP

L’unità px rappresenta I pixel reali dello schermo. Spesso però gli schermi degli smartphone hanno densità differenti, deve per densità si intende il PPI, numero di pixel per pollice lineare.

Ad esempio due smartphone differenti possono avere rispettivamente schermi da 4,5” (diagonale) e 7” ed avere entrambi una risoluzione di 720 x 1280 (16:9). Significa che il secondo smartphone ha una densità di pixel inferiore, cioè i pixel sono più lontani tra loro. Entrambi possono visualizzare lo stesso identico contenuto, ma il secondo lo visualizza in modo più ingrandito (però con minore definizione, avendo un PPI inferiore). Se si ritiene che la visibilità sul primo smartphone sia suffciente, le dimensioni dell’immagine sul secondo smartphone potrebbero essere ridotte in modo da poter viualizzare più cose

Viceversa due smartphone con uno stesso schermo da 5” possono evere risoluzione diversa, ad esempio il secondo pari al doppio del primo. Significa che il secondo smartphone ha un PPI doppio e quindi può visualizzare il doppio delle cose, ciacuna con dimensioni dimezzate. Spesso nel progettare il layout di una app si tende ad assegnare ai vari oggetti una dimensione fissa, indipendente dal PPI del dispositivo. Questo riultato è stato ottenuto grazie all’introduzione dell’unità di misura DP Density-independent Pixels. Si supponga di voler visualizzare una immagine con dimensione ½ pollice x ½ indipendentemente dal PPI del dispositivo.

Su un dipositivo con PPI = 120 l’immagine dovrà estendersi per 60 x 60 pixel Su un dipositivo con PPI = 240 l’immagine dovrà estendersi per 120 x 120 pixel, cioè dovrà essere il doppio rispetto all’immagine precedente. Poiché è impensabile memorizzare immagini diverse per ogni possibile PPI del dispositivo, sono stati definiti degli appositi Density Bucket (secchielli di densità):

Density Bucket name DPI from…. to…… density

ldpi low 120 dpi 100 140 0,75

mdpi medium 160 dpi 140 180 1

hdpi height 240 dpi 180 280 1,5

xhdpi extra height 320 dpi 280 360 2

xxhdpi extra extra height 480 dpi 400 3

Per ognuno di questi Density Bucket è stata predisposta una apposita cartella all’interno delle risorse. Per poter gestire l’imagine precedente con dimensioni fisse di ½ pollice x ½ pollice, occorre creare cinque immagini con grandezza differente salvandole nelle apposite cartelle. Le varie immagini dovranno avere le dimensioni indicate nel seguente prospetto:

Page 23: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 23

A seconda del PPI del dispositivo la app visualizzerà l’immagine opportuna. E’ anche possibile memorizzare una sola immagine (in genere quella con risoluzione maggiore). In caso di assenza delle immagini con risoluzione diversa, la app provvederà automaticamente a riscalare l’immagine espressa in dp in modo da ottere le dimensioni opportune. Istruzioni per la converione da px a dp

Anche impostando tutte le dimensioni in DP, molte funzioni relative al layout restituiscono o si aspettano le dimensioni degli oggetti in px, per cui per poterle riassegnare in dp occorre eseguire una conversione manule da dp a px, utilizzando ad esempio il seguente metodo:

context.getResources().getDisplayMetrics().density;

che restituisce il valore density del ispositivo, come indicato nell’ultima colonna della tabella precedente

Per semplificare la scrittura si possono predisporre le seguenti funzioni:

public int dpToPx(int dp) {

float density = this.getResources().getDisplayMetrics().density;

return Math.round((float) dp * density);

}

public int pxToDp(int px) {

float density = this.getResources().getDisplayMetrics().density;

return Math.round((float) px / density);

}

La casella di testo : il widget EditText

La proprietà inputType consente di definire il comportamento della Casella di Testo :

inputType = "none" qualsiasi carattere

inputType = "text" solo caratteri testuali

inputType = "number" solo numeri. In corrispondenza del click si apre il tasterino numerico

inputType = "password" visualizza asterischi

hint = "Inserisci il tuo testo" suggerimento iniziale

Quando l'utente clicca su un oggetto di tipo EditText appare automaticamente una tastiera virtuale sullo schermo del dispositivo che permette l'immissione del testo. La chiusura della tastiera quando l'utente termina l'immissione del testo non è invece implementata direttamente nella tastiera, ma occorre aggiungere un bottone particolare che consenta di rimuovere la tastiera dallo schermo. Per arricchire la tastiera con il tasto done occorre inserire la seguente riga:

input.ImeOptions = Android.Views.InputMethods.ImeAction.Done;

Ha l'effetto di settare un IME nella tastiera.

Un IME (input method) implementa un particolare modello di interazione che l'utente può utilizzare. Il tipo di IME da aggiungere alla tastiera deve essere passato come argomento alla proprietà ImeOptions. I principali tipi IME (mutuamente esclusivi) sono:

DONE

GO Nel caso di campi URL invia la richiesta HTTP al server

NEXT Passa al campo successivo

SEND Invia il testo ad un servizio specifico

Page 24: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 24

La gestione delle immagini : il widget ImageView

Consente di visualizzare un'immagine memorizzata all’interno della cartella res / drawable

Nel caso di immagini di dimensioni superiori alla risoluzione del controllo, Android effettua un resize automatico in modo da renderla completamente visibile (non esagerare comunque con le dimensioni).

Aggiungere una immagine nella cartella xhdpi

Così come per i Layout, anche per le res i nomi dei files devono essere scritto in minuscolo.

Impostazione dell’immagine sul Layout Grafico. Trascinare un oggetto ImageView : android:src="@drawable/desert" // senza estensione !!

Impostazione dell’immagine da codice : ImageView img=FindViewById<ImageView>(Resource.Id.image);

img.SetImageResource(Resource.Drawable.img01); // senza estensione !!

Il metodo Resources.GetIdentifier()

Consente di eseguire un accesso diretto a tutte le risorse identificate, come ad esempio

Le risorse memorizzata all’interno della cartella res (es Resource.Id.image)

I controlli identificati tramite un ID statico (es Resource.id.btn1)

Sia Resource.drawable.image che Resource.id.btn1 sono costanti esadecimali, per cui NON

possono essere utilizzate all’interno di un ciclo per accedere ad un elenco di oggetti con nomi simili (e img1, img2, img,3, btn1, btn2, btn3, etc).

Il metodo consente di accedere all’oggetto indicato e di ottenere il suo ID esadecimale a partire dalla

stringa identificativa. Sintassi:

int imageToSee = 1;

img.SetImageResource(Resources.GetIdentifier("img" +

imageToSee.ToString("00"), "drawable", PackageName));

Restituisce l’ID numerico dell’oggetto cercato, oppure 0 se non lo trova.

Page 25: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 25

Gestione dello schermo

Rotazione dello schermo

if (RequestedOrientation == ScreenOrientation.Portrait) RequestedOrientation = ScreenOrientation.Landscape; else RequestedOrientation = ScreenOrientation.Portrait;

Attenzione che la rotazione del video provoca la terminazione dell’Activity e successivo riavvio con rigenerazione dell’evento onCreate. Questo di per sé non è un gravissimo problema e non inficia il buon funzionamento della rotazione, ma il riavvio dell’applicazione può comunque creare fastidi. Ad esempio se il contenitore imageView all’avvio caricava staticamente una immagine, questa viene ricaricata ad ogni rotazione.

Per evitare che in corrispondenza della rotazione dell’immagine venga riavviata l’Activity, occorre aggiungere la seguente riga:all’interno del Manifest:

<activity android:name = "MainActivity"

android:configChanges = "orientation|keyboardHidden|screenSize">

Più comodamente all’interno della classe dell’activity: [Activity(Label = "@string/app_name”, ConfigurationChanges =

Android.Content.PM.ConfigChanges.Orientation |

Android.Content.PM.ConfigChanges.KeyboardHidden |

Android.Content.PM.ConfigChanges.ScreenSize)]

Questa riga fa sì che, in caso di variazione della orientation del telefono, oppure in caso di nascondimento della tastiera, oppure in caso di variazione dello sceenSize, l’applicazione non si riavvii, ma generi semplicemente un evento onConfigurationChanged che può essere gestito o meno.

Lettura delle Dimensioni dello schermo

DisplayMetrics metrics = new DisplayMetrics();

Display display = this.WindowManager.DefaultDisplay;

display.GetMetrics(metrics);

show("WidthPixel: "+ metrics.WidthPixels + " - HeightPixel:

"+metrics.HeightPixels);

Check Box e Radio Button

A fianco di ogni Check Box / Radio Button viene sempre visualizzato un TextView contenente un testo associato al controllo. Non esiste il concetto di value I Radio Button sono mutuamente esclusivi soltanto se inseriti all’interno di un medesimo RadioGroup (avente ad esempio id = optGroup). Non sono mutuamente esclusivi i Radio Button inseriti

direttamente all’interno di un Layout o altro. Esempi di utilizzo:

if (myOpt.Checked) {

myOpt.Text(“checked”);

myOpt.Checked=false; }

int id_elemSelez = optGroup.CheckedRadioButtonId;

RadioButton opt = FindViewById<RadioButton>(id_elemSelez);

Page 26: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 26

In corrispondeza del click si può utilizzare il seguente evento :

chk.CheckedChange += Chk_CheckedChange;

private void Chk_CheckedChange(object sender,

CompoundButton.CheckedChangeEventArgs e)

{

}

Impostazione delle proprietà tramite designer

I valori fill_parent e match_parent sono equivalenti. Il primo è deprecato a favore del secondo

text = “testo del controllo”. Utilizza istanze implicite, per cui va bene eseguire il confronto con ==

tag = Campo nascosto di tipo object molto comodo per salvare valori di appoggio (id record)

Utilizza istanze eplicite per cui occorre necessariamente utilizzare .equals()

textSize = "18dp" // Il valore di default dipende dal tipo di controllo textStyle = "bold|italic"

typeFace = famiglia del font

padding = "10dp" // Il padding non viene aggiunto a width e height come in html, ma provoca

semplicemente uno spostamento del testo. Se ad esempio si imposta un allineamento del testo a sinistra, conviene dare un piccolo paddingLeft. In questo caso il paddingRight non viene ‘sentito’. In caso di allineamento centrato, si può dare un paddingLeft negativo per spostare il testo verso sinistra ed un paddingTop positivo per abbassare un pochino il testo.

gravity = ancoraggio del testo rispetto alle dimensioni dell’oggetto. Ad esempio un TextView può

avere larghezza 200dp ma un testo interno molto breve che può essere allineato nel modo seguente:

LEFT A sinistra

RIGHT A destra

TOP In cima al contenitore

BOTTOM Al fondo del contenitore

CENTER Al centro del contenitore, rispetto sia all’asse X che all’asse Y Questi valori possono essere combinati tra loro tramite una OR bit a bit.

Es Gravity.LEFT | Gravity.BOTTOM

enabled = true / false // Disabilita il controllo

editable = true / false // Usato nei TextView

visibility = visible / unvisible

textColor = "#ffff00" // colore del testo

background = "#0000ff" // colore di sfondo background = "@android:color/holo_blue_dark"

layout_width="185dp” // larghezza del controllo

layout_height="wrap_content" // altezza del controllo adattata al contenuto

layout_margin=”10dp” // margini esterni.

layout_gravity // ancoraggio dell’oggetto rispetto al Layout.

layout_weight=1; // copertura dell’area libera all’interno ad esempio di un

layout orizzonale.

Il valore layout_gravity =Gravity.Right ha senso ad esempio nel caso di un LinearLayout

verticale in cui l’oggetto occupa tutta la riga. Se l’oggetto corrente ha dimensioni ridotte, impostando layout_gravity =Gravity.Right l’oggetto viene ancorato sul lato destro del

contenitore lasciando libero lo spazio antecedente

Page 27: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 27

Nel caso invece di un LinearLayout orizzontale in cui gli oggetti i susseguono uno dopo l’altro, l’imposatzione layout_gravity =Gravity.Right applicata ad esempio all’ultimo controllo non

sortisce nessun effetto perché si verrebbe a creare davanti all’oggetto uno spazio vuoto che il designer non sa dove posizionare.

Nel caso di un layout orizzontale, la proprietà layout-weight=1 consente di definire quale peso

avrà il controllo nella ridistribuzione degli spazi liberi all’interno della riga. Il valore di default è 0. Se si assegna il valore 1, il controllo coprirà l’intera area libera della riga. A tal fine è però necessario che il contenitore abbia una width pari a MatchParent. Sull’elemento occorre poi impostare il gravity del testo interno rispetto all’elemento, in modo da allineare il testo a sinistra rispetto al controllo (con la spaziatura a destra) oppure a destra (con la spaziatura a sinistra).

Attenzione che la propriatà gravity, vale SOLO ed ESCLUSIVAMENTE per i testi per cui non può essere utilizzata, ad esempio, per gli imageView. Nel caso di check box / radio button provoca l’allineamento del testi ma NON l’allineamento del quadratino / cerchietto.

Riguardo al width del controllo su cui si imposta layout-weight=1 si può utilizzare qualsiasi

valore intanto la larghezza viene poi calcolata automaticamente sulla base dell’area libera. Normalmente è consigliato il valore 0.

Volendo ridistribuire l’area libera in modo proporzionale si può impostare sul layout ad esempio weightSum=5, sul primo controllo weight=1, sul secondo weight=3, sul terzo weight=1

Impostazione delle proprietà tramite codice

Per l’accesso da codice alle Property occorre utilizzare le relative Property dell’oggetto che come unità di misura utilizzano SOLTANTO i pixel, per cui spesso occorre eseguire manualmente le conversioni necessarie.

.Text restituisce il testo del widget. Spesso occorre fare .toString()

setta il testo del widget .TextSiz =16; imposta la dimensione del testo in dp .Typeface = Android.Graphics.Typeface.SansSerif; // font-style

.SetTypeface(Typeface.SansSerif,TypefaceStyle.Bold); // font-style + bold

.SetTypeface(null, Typeface.Italic); // come font-style usa il default

.setTypeface(null, Typeface.ITALIC);

.setTypeface(null, Typeface.NORMAL);

.setTypeface(null, Typeface.BOLD_ITALIC);

.setPadding(6,6,6,6); I valori di Padding e Margin partono da LEFT / TOP / RIGHT / BOTTOM

.PaddingLeft = 6;

.Gravity = Android.Views.GravityFlags.CenterVertical; // Allineamento del testo

.Enabled = true;

.Editable = false;

. Visibility = Android.Views.ViewStates.Invisible;

.bringToFront() porta il widget corrente in primo piano.

Le proprietà di tipo layout

Tutte le proprietà dei singoli controlli che interagiscono con il layout (cioè width, height, margin, gravity del controllo rispetto al layout, etc.) e che, nel designer, iniziano con la parola layout, devono essere definite tramite la property LayoutParameters. ES

var layoutParameters = ((Button) sender).LayoutParameters;

layoutParameters.Width = 800;

Page 28: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 28

Nel caso creazione di una istanza ex-novo, occorre passare al costruttore i valori di width e height : (solo in alcuni casi (es TableRow) è ammesso un costruttore privo i parametri).

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(300,

LinearLayout.LayoutParams.WRAP_CONTENT);

params.width=50; // sovrascrive il 300 passato al costruttore

params.setMargins(6,6,6,6);

params.setMarginLeft(6);

params.gravity= Gravity.CENTER_VERTICAL;

params.weight=1.0f; // oppure =1; sembra indifferente

btn.setLayoutParams(params);

LinearLayout.LayoutParams par = new LinearLayout.LayoutParams(300,

LinearLayout.LayoutParams.WrapContent);

par.Width = 50;

par.SetMargins(5, 5, 5, 5);

par.LeftMargin = 8;

par.Gravity = GravityFlags.CenterVertical;

par.Weight = 1.0f;

((Button) sender).LayoutParameters = par;

// oppure, nel caso si vogliano impostare soltanto width e height, si può semplicemente fare: ((Button) sender).LayoutParameters = new

LinearLayout.LayoutParams(300, 400);

Immagine di sfondo di un pulsante

((Button) sender).SetBackgroundResource(Resource.Drawable.img01);

In alternative esiste un comodo pulsante imageButton.

Creazione Dinamica dei controlli

Il layout di una Activity può essere creato dinamicamente da codice anche senza l’ausilio di un file xml.

Button btn=new Button(this);

btn.Text = "Bottone" + i + 1;

btn.Id = i + 1;

btn.Click += (sender, e) =>

{

Button b = sender as Button;

Toast.MakeText(this, "Premuto pulsante "+b.Id,

ToastLength.Long).Show();

};

layout.AddView(btn);

Note sulla gestione dell’Id

L’Id è in realtà un numero intero esadecimale utilizzato per identificare ciascun controllo (View). L’Id può essere assegnato staticamente all’interno del file XML oppure dinamicamente da codice.

Assegnazione statica dell’ID all’interno del layout

android:id=”@+id/button1”

Page 29: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 29

Il valore dell’attributo id deve essere univoco sull’intera applicazione. Il compilatore trasforma questa stringa alfanumerica in un intero positivo esadecimale univoco.

Riferimento al controllo : findViewById

Per accedere da codice al controllo si utilizza il metodo findViewById : CheckBox chk = FindViewById<CheckBox>(Resource.Id.checkBox1);

Accesso all’ID esadecimale del controllo : getId()

Mentre il metodo findViewById restituisce un riferimento al controllo partendo dall’ID,

l proprietà v.Id eegue l’operazione invesa, cioè restituisce la costante esadecimale del controllo a

partire dal riferimento

if( v.Id == Resource.Id.button1)

Assegnazione dinamica dell’ID tramite codice

L’assegnazione può essere eseguita semplicemente mediate la Proprietà .Id = dove il parametro

deve essere un numero > 0 non necessariamente univoco e che può anche essere in conflitto con un id statico. L’univocità dell’ID è importante soltanto dal punto di vista logico-funzionale. Lo 0 ha il significato di risorsa non trovata

A differenza di Java è consentito assegnare direttamente un valore numerico alla proprietà .

L’API 17 ha introdotto il metodo statico View.generateViewId() che consente di generare ID

univoci. Riferimento al controllo creato dinamicamente

Dopo aver creato il controllo e aggiunto al layout, l’accesso può essere eseguito nel solito modo: Button btn = FindViewById<Button>(id);

Come è possible consentire id non univoci ?

Il fatto che l’ID non debba essere necessariamente essere univoco si spiega con il fatto che, quando si ricerca di un controllo appartenente al Layout tramite findViewById, esso esegue una semplice

ricerca sequenziale restituendo il primo controllo avente l’ID indicato. Poiché nella lista dei controlli quelli creati staticamente a Design Time si trovano sicuramente prima di quelli creati dinamicamente, findViewById restituirà sempre il controllo statico (che in certi casi potrebbe essere un problema).

Se si usa la crazione dinamica è MEGLIO creare tutto dinamicamente.

Page 30: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 30

Layout

LinearLayout

Era il layout di default fino alla versione 4.x. Dispone gli elementi uno di seguito all'altro.

La proprietà orientation (vertical o horizontal=defaut) consente di impostare il layout:

verticale - gli elementi vengono disposti uno sotto l'altro (uno per riga)

orizzontale - gli elementi vengono disposti uno dopo l'altro da sinistra verso destra (tutti sulla

stessa riga). In questo caso i vari elementi dovranno avere width="wrap_content" e NON

width="match_parent" altrimenti si vedrebbe un solo controllo.

In entrambi i casi gli elementi vengono aggiunti alla finestra finchè c'è spazio . Se si richiede l'inserimento di un ulteriore elemento, android cerca di ridimensionarlo (peraltro in modo molto poco leggibile) per inserirlo comunque all'interno dello schermo. Questo comportamento è limitato ad una soglia oltre la quale, semplicemente, gli elementi aggiuntivi non vengono più visualizzati.

La proprietà layoutDirection consente visualizzare i controlli interni da sinistra verso destra

(LAYOUT_DIRECTION_LTR) oppure da destra verso sinistra (LAYOUT_DIRECTION_RTL)

La proprietà gravity del LinearLayout consente di definire la posizione dei i wdget interni.

RelativeLayout

Layout di default dalla versione 5 in avanti. Consente di posizionare liberamente gli elementi indicando dimensione e posizione. Invece dei valori assoluti è possibile getire l’allineamento di un elemento rispetto agli elementi circotanti. Esempi :

Il primo elementi potrà avere:

android:layout_alignParentLeft="true"

android:layout_alignParentTop="true"

android:layout_marginTop="10dp"/>

Il secondo elemento potrà, ad esempio, essere posizionato sotto il primo:

android:layout_below="@+id/idElementoPrecedente "

android:layout_centerHorizontal="true"

Il terzo elemento potrà essere posizionato a fianco del secondo:

android:layout_toRightOf="@+id/idElementoPrecedente"

Il quarto elemento potrà essere centrato nella pagina:

android:layout_gravity="center_horizontal"

android:layout_centerHorizontal="true"

android:layout_centerVertical="true"

Impostazione da codice

Le proprietà precedenti, disponibili soltanto nel caso del RelativeLayout, sono dette rules e sono impostabili da codice nel modo seguente:

RelativeLayout.LayoutParams params = (cast) v.getLayoutParams();

Se però l’oggetto è stato creato dinamicamente v.getLayoutParams()restituice null.

Page 31: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 31

Occorre allora istanziarlo ex-novo passandogli al solito width e height

RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(

RelativeLayout.LayoutParams.WRAP_CONTENT,

RelativeLayout.LayoutParams.WRAP_CONTENT);

params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);

params.addRule(RelativeLayout.ALIGN_PARENT_TOP);

params.addRule(RelativeLayout.BELOW, R.id.previous);

params.addRule(RelativeLayout.RIGHT_OF, Resource.id.previous);

params.addRule(RelativeLayout.CENTER_HORIZONTAL);

params.addRule(RelativeLayout.CENTER_VERTICAL);

btn.setLayoutParams(params);

Pr quanto riguarda la rimozione di una regola, esistono due sintassi, la prima antecedente alla versione 17 ma ancora oggi supportata, la seconda disponibile dalla versione 17 in avanti:

params.addRule(RelativeLayout.CENTER_HORIZONTAL, 0);

params.removeRule(RelativeLayout.CENTER_HORIZONTAL);

TableLayout

Permette di organizzare i contenuti come se si stesse lavorando con una tabella. L’organizzazione avviene tramite l’oggetto TableRow che identifica una riga della tabella All'interno di questo oggetto

dovremo inserire tutti gli elementi che vogliamo mostrare in quella specifica riga. Es di matrice 4 x 4

TableLayout layout = (TableLayout) findViewById(R.id.tableLayout);

for (int i = 0; i < 4; i++) {

TableRow riga = new TableRow(this);

riga.setGravity(Gravity.CENTER);

for (int j = 0; j < 4; j++) {

Button btn = new Button(this);

btn.setId(i * 4 + j);

btn.setText("");

btn.setOnClickListener(myListener);

riga.addView(btn);

}

layout.addView(riga);

}

Attenzione che eventuali parametri devono essere d tipo TableRow e non di tipo TableLayout.

FrameLayout

Il Frame Layout consente la sovrapposizione dei controlli, che vengono posizionati su piani crescenti in base alla posizione del controllo all’interno del Layout. In pratica mentre il Linear Layout consente di disporre consecutivamente i controlli in verticale oppure in orizzontale, il Frame Layout consente di impilarli lungo l’asse z, uno per piano. Il metodo bringToFront() consente di spostare l’elemento corrente in cima alla pila. Per ogni controllo si può inoltre specificare, tramite layout_gravity, il tipo di ancoraggio

(con i soliti 9 valori: top, bottom, left, right, fill, top|left, top|right, bottom|left, bottom|right).

ConstraintLayout

Simile a RelativeLayout ed utilizzato come Layout di default nelle ultime version di Android studio. https://developer.android.com/training/constraint-layout/index.html

Page 32: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 32

Associazione di un layout ad una Activity

SetContentView(Resource.Layout.activity_main);

Quando si cambia layout associato all’activity, il layout viene ‘ricreato’, per cui non mantiene i valori precedenti. Non solo, ma di conseguenza occorre anche reinizializzare i vari puntatori ai controlli dei

layout ripetendo tutti i vari findViewById.

Dimensioni dell’Area client di un layout

Android.Views.Window window = this.Window;

View clientArea = Window.FindViewById(Window.IdAndroidContent);

int width = clientArea.Width;

int height = clientArea.Height;

Navigazione all’interno di un layout

Int n=layout.ChildCount; restituisce il numero di controlli presenti all’interno del layout

layout.GetChildAt(i); restituisce il puntatore all’oggetto i-esimo figlio del layout (a base 0)

IViewParent p=this.Parent; restituisce il puntatore all’elemento genitore.

Cancellazione di elementi

layout.RemoveAllViews(); elimina tutti i controlli contenuti all’interno del layout

layout.RemoveView(view); elimina uno specifico controllo all’interno del layout

layout.RemoveView(layoutInterno); elimina un intero layout contenuto all’interno di un altro

layout e tutti i controlli in esso contenuti Scroll di un Layout

Per rendere un Linear Layout scrollable è sufficiente racchiuderlo all’interno di un oggetto ScrollView

<ScrollView android:layout_width="match_parent"

android:layout_height="match_parent" >

<LinearLayout> </LinearLayout>

</ScrollView>

Page 33: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 33

INTENT

Gli intent rappresentano uno degli aspetti più importanti di Android. Un Intent è un messaggio (oggetto istanziabile) che una APP può inviare al Sistema Operativo per richiedere una certa azione, come ad esempio l’esecuzione di una Activity o di un Service. Un intent può contenere al suo interno tre informazioni:

action, cioè l’azione da eseguire. L’azione da eseguire può essere l’avvio di una activity, la

visualizzazione di un documento, l’editazione di un documento, la riproduzione di un filmato o altro ancora. Possibili valori di action sono i seguenti:

ACTION_MAIN Richiesta di Avvio di un componente. Non ha dati in input ACTION_VIEW Richiesta di visualizazione di un insieme di dati indicati tramite URI ACTION_EDIT Richiesta di accesso in editazione a un insieme di dati indicati tramite URI ACTION_ECHO Riproduzione di un file video / audio indicato tramite URI

uri, indica la risorsa da eleborare. Ad esempio una pagina web da visualizzare, un documento

PDF da visualizzare, un numero di telefono da contattare. URI (Uniform Resource Identifier) è una sequenza di caratteri che identifica univocamente una risorsa generica. Sono esempi di URI: un indirizzo web (URL), un documento, un'immagine, un file, un servizio, un indirizzo di posta elettronica simile. URL è strettamente legato alle risorse web, mentre URI è più generico. Si può dire “tutti gli URL sono URI, ma esistono URI che non sono URL. Esempi di URI:

String uri = "http://www.google.com"; (URL)

String uri = "tel:3337684747";

String uri = "sms:3337684747";

String uri = "mailto:[email protected]";

destinatario finale del messaggio. Può essere un’Activity, un Servizio o un Broadcast

Receiver. E’ l’elemnto a cui il SO dovrà inoltrare il messaggio ricevuto. Oltre a quete informazioni un intent può contenere al suo interno dei parametri aggiuntivi (detti Extras) che saranno inoltrati al destinatario insieme al messaggio. Ad esempio nel caso di una mail i vari extras potrebbero essere l’oggetto, il body, i destinatari per conoscenza, i destinatari per conoscenza nascosta, etc. Intent Espliciti ed Impliciti

Si parla di Intent Esplicito quando è esplicitamente indicato il destinatario del messaggio. Si parla di Intent implicto quando NON è esplicitamente indicato il destinatario del mesaggio

Per istanziare un Intent esistono varie firme differenti, tra le quali :

1) Intent intent = new Intent()

Istanzia un Intent anonimo. Azione, URI e destinatario verranno specificati in seguito

2) Intent intent = new Intent(Intent o)

Costruttore per copia. Istanzia un Intent copiandolo da un altro Intent passato come parametro.

3) Intent intent = new Intent(String action)

Istanzia un Intent implicito relativo ad una specifica azione, senza indicare però l’URI

4) Intent intent = new Intent(String action, Uri uri)

Firma tipica per l’Istanza di un Intent Implicito, in cui viene indicata una specifica azione ed uno specifico URI, ma non viene indicato il destinatario

Page 34: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 34

5) Intent intent = new Intent(Context packageContext, Class cls)

Firma tipica per l’Istanza di un Intent Esplicito in si indica esplicitamente il destinatario dell’intent. In caso di intent esplicito solitamente non serve indicare né l’action (che sarà quella predefinita del destinatario) né la URI nel caso in cui il destinatario non debba elaborare una risorsa specifica. Con questa firma, il SO non esegue di solito nessuna valutazione sull’action da eseguire e si limita ad avviare il componente indicato.

6) Intent intent = new Intent(String action, Uri uri, Context

packageContext, Class<?> cls)

Firma complete per l’istanzia di un Intent esplicito, contenente però anche la action da eseguire e la risorsa su cui operare. Esempio di istanza di un intent implicito

Intent intent1 = new Intent();

intent1.SetAction("android.intent.action.Activity2");

StartActivity(intent1);

Esempio di istanza di un intent esplicito

Intent intent = new Intent(this, typeof(Activity2));

this.StartActivity(intent);

Utilizzo degli intent impliciti

Nel caso di intent implicito, in che modo il Sistema Operativo riesce ad individuare il destinatrio del messaggio ? Quando si definisce un componente, attraverso il cosiddetto intent-filter è possibile

dichiarare che quel componente è in grado di rispondere a specifici messaggi. L’ intent-filter

può essere definito staticamente all’interno del Manifest, oppure anche dinamenicamente all’interno del codice dell’Activity, Servizio o Broadcast Receiver.

In corrispondenza di un Intent implicito il SO provvderà ad individuare tutti i receiver compatibili. Nel caso in cui esistano più componenti registrati con lo stesso intent-filter, verrà richiesto all’utente di decidere quale componente utilizzare per avviare l’attività. Ad esempio l’activity principale di un browser avrà, all’interno del Manifest, un Intent-filter de tipo seguente:

<activity android:name=".BrowserActivitiy">

<intent-filter>

<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />

<data android:scheme="http" />

</intent-filter>

</activity>

Page 35: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 35

Cioè questa activity verrà avviata tutte le volte che verrà richiesta una action di tipo ACTION_VIEW per

una risorsa avente un URI che inizia con i caratteri http:

L’attributo data

Indica il tipo di risorsa che il componente è in grado di servire. Il componente sarà in grado di servire tutte le risorse il cui URI inizia con i caratteri indicati all’interno dell’attributo data.

L’attributo mimeType

Serve ad identificare meglio (all’interno dell’attributo data) il tipo di risorsa che il componente è in grado di servire. Ad esempio un riproduttore audio / video che è in grado di riprodurre qualunque file audio e soltanto i video mpeg potrà avere un attributo mimeType come indicato di seguito.

<intent-filter>

<action android:name=”android.intent.action.ECHO” />

<data android:scheme=“http” android:mimeType=“audio/* />

<data android:scheme=“http” android:mimeType=“video/mpeg />

</intent-filter>

L’attributo category

Fornisce una informazione aggiuntiva rigiardo all’azione da eseguire. category.LAUNCHER indica che il componente dovrà essere visualizzato nel Launcher come una

top-level application (elenco delle applicazioni disponibili all’interno dello smartphone) category.DEFAULT indica che il componente deve essere considerato come un componente di

default in grado di soddisfare l’azione indicata. category.ALTERNATIVE indica che il componente dovrà essere incluso in una lista di componenti

alterntivi comunque in grado di soddisfare l’azione indicata Se un componente non definisce un apposito intent-filter, potrà essere avviato soltanto tramite un intent esplicito.

Manipolazione dell’intent dell’ AndroidManifest.xml con Xamarin

A partire da Xamarin.Android 5.1 il nome di un’activity è basato su l’MD5SUM dell’assembly-qualified name. Ciò consente di fornire lo stesso nome a due assemblaggi differenti e non avere errori al momento del deploy dell’app per nome duplicato. Prima di Xamarin.Android 5.1 il nome invece veniva creato andando a comporre il namespace in minuscolo più il nome della classe. Se si vuole andare a modificare questo nome predefinito (siccome il manifest viene “creato” quando l’app va in compilazione) bisogna andare ad utilizzare la property [Activity (Name="awesome.demo.activity")]. Es.: [Activity(Label = "Activity2", MainLauncher = false)]

[IntentFilter(new[] { "android.intent.action.Activity2" }, Categories =

new[] { Intent.CategoryDefault})]

Nell’esempio si vede anche come andare ad esplicitare l’intent filter che permetterà la chiamata in modo implicito.

Page 36: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 36

Metodi per l’invio di un intent al Sistema Operativo

startActivity(intent)

Se si intende inviare il messaggio ad una activity di una app

startService(intent)

Se si intende inviare il messaggio ad un servizio di background in esecuzione sullo smartphone

sendBroadcast(intent)

Se si intende inviare il messaggio in broadcast a tutte i componenti dello smartphone

Richiamo di una Activity mediante un intent esplicito

Per creare una nuova Activity si dovrà creare una nuova classe che estenda Activity. Per ciascuna Activity si può creare un apposito layout di riferimento. In realtà però una Activity1 potrebbe utilizzare più Layout diversi senza necessità di dover istanziare una seconda Activity2. Il fatto di creare due Activity separate, ognuna con il suo layout, consente di suddividere meglio il codice

L’activity principale presenta di default un intent-filter di questo tipo:

<activity android:name=".MainActivity">

<intent-filter>

<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>

</intent-filter>

</activity>

Il valore ACTION_MAIN indica una activity di tipo MAIN direttamente eseguibile dal sistema operativo.

Il valore category.LAUNCHER indica che l’activity dovrà essere visualizzata all’interno del Launcher

con una sua icona. In linea di massima all’interno di una APP una sola Activity può essere di tipo MAIN / LUNCHER. Nel caso di più Activity di questo tipo, l’Activity da lanciare all’avvio dovrà essere

specificata all’interno della finestra EDIT CONFIGURATION. Le activity secondarie possono, facoltativamente, essere dichiarate con il seguente intent-filter :

<intent-filter>

<action android:name="android.intent.action.startSecondActivity"/>

<category android:name="android.intent.category.DEFAULT"/>

</intent-filter>

dove action startSecondActivity indica l’azione a cui questa activity dovrà rispondere (in

pratica ne indica sostanzialmente il proprio nome) Come riportare una Activity in primo piano

Per riportare una Activity in primo piano è sufficiente settare un apposito flag prima di eseguire

startActivity. In questo modo l’Activity non viene re istanziata ma solo riportata in primo piano.

Intent intent = new Intent(this, typeof(MainActivity));

intent.AddFlags(ActivityFlags.ReorderToFront);

StartActivity(intent);

Page 37: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 37

Ciclo di vita di una Activity

onCreate : evento richiamato al momento del caricamento in memoria

onPause : evento che si verifica quando viene aperta una nuova activity e l’activity corrente, pur

rimanendo visibile, non è più in esecuzione (equivalente allo stato di ready dei processi) Gli eventi onPause e onResume sono utilizzati per attivare/terminare servizi che devono attivi solo

quando l'activity è in uso

onStop : Quando una Activity lancia in esecuzione un’altra Activity tramite un Intent, automaticamente

passa nello stato di STOP, cioè si trova nello stack delle Activity in esecuzione ma non è al momento visibile. Nel momento in dovesse essere riavviata non viene più generato l’evento onCreate ma gli eventi onRestart e onStart. Il Sistema Operativo ha facoltà di ‘killare’ il

processo nel caso di satuazione della memoria (il processo che viene terminato è quello che si trova in fondo allo stack, cioè quello con utilizzo più lontano nel tempo. Se l’Activity viene fatta ripartire mediante il flag REORDER_TO_FRONT, questa ripatirà generando l’evento START. Idem se l’Activity viene di nuovo a trovarsi in primo piano per la chiusura della Activity che si trovava in esecuzione.

Tutti questi eventi devono, per prima cosa, richiamare l’evento corrispondente della super-classe, esattamente come avviene per onCreate(). Però, a differenza di onCreate non hanno parametri.

onStop()

Page 38: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 38

onDestroy : Quest’evento si verifica quando l’actvity viene terminata esplicitamente mediante il

metodo Finish oppure mediante il tasto BACK dello smartphone. Il metodo Finish() ed il pulsante BACK

il pulsante Back dello smartphone ed il metodo Finish() provvedono a terminare l’activity corrente rimuovendo fisicamente l’istanza dalla memoria e generando l’evento onDestroy. Il metodo Finish() è un metodo relativo al contesto corrente:

this.Finish();

Notare che il tasto App recenti dello spartphone apre una schermata con le applicazioni usate recentemente sotto forma di anteprima. In questo elenco compaiono

sia le app in stato di stop (che mantengono lo stato attuale)

sia le app terminate tramite finish o pulsante BACK che, viceversa, non mantengono lo stato. In corrispondenza del loro riavvio verrà rigenerato l’evento onCreate()

In Lollipop è stata introdotta una grafica a carosello che facilita un rapido passaggio da un'app all'altra Il metodo MoveTaskToBack(true) e l’apertura di una una nuova Activity

In entrambi i casi l’activity viene portata in stato di stop (cioè in background). Quando l’Activity ritornerà in primo piano verranno generati gli eventi onRestart() e poi onStart(), ma NON onCreate(). Il parametro True fa sì che la app venga minimizzata anche se il focus non è sulla Activity principale. False invece prvoca la minimizzazione solo se il focus è sulla activity principale.

Passaggio di parametri ad una Activity

Qualunque sia la definizione dell’intent, prima di richiamare il metodo startActiity(intent), si

possono aggiungere all’interno dell’intent eventuali parametri (detti Extras) da passare alla seconda

Activity, facendo uso del metodo

intent.PutExtra("nomeParametro", valore);

intent.PutExtra("parametro1","Ciao");

intent.PutExtra("parametro2", (float) 77.77); // default double

intent.PutExtra("parametro3", new int[]{23, 12, 54});

intent.PutStringArrayListExtra("parametro4", myList);

this.StartActivity(intent);

Lettura dei parametri in Activity2

Activity2 può accedere ai parametri ricevuti nel modo seguente:

Intent intent = this.Intent;

if(intent!=null && intent.HasExtra("parametro1"))

parametro1 = intent.GetStringExtra("parametro1");

if(intent!=null && intent.HasExtra("parametro2"))

parametro2 = intent.GetFloatExtra("parametro2", 0); (0=defaultValue) parametro3 = intent.GetIntArrayExtra("parametro3");

myList = intent.GetStringArrayListExtra ("parametro4");

In alternativa al passaggio dei parametri, queste variabili potrebbero essere dichiarate statiche dentro Activity1 diventando così accessibili da Activity2 semplicemente come Activity1.parametro1

Page 39: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 39

Restituzione di un risultato

Se Activity1 intende ricevere una risposta da Activity2, in fase di chiamata non deve utilizzare il metodo StartActivity(), ma StartActivityForResult() passandogli come secondo parametro un

codice identificativo della richiesta :

private const int CODICE_RICHIESTA=1234;

this.startActivityForResult(intent, CODICE_RICHIESTA);

Activity2, una volta letti i parametri ed eseguite le azioni necessarie, potrà presentare all’utente due pulsanti OK e CANCEL che provvederanno ad inviare all’utente due risultati differenti.

Button btnOK = FindViewById(Resource.Id.btnOk) as Button;

btnOK.Click += (sender, e) =>

{

Intent intent1 = new Intent();

intent1.PutExtra("chiudi", true);

intent1.PutExtra("param", "Cliccato OK");

this.SetResult(Result.Ok,intent1);

this.Finish();

};

Button btnAnnulla = FindViewById(Resource.Id.btnAnnulla) as Button;

btnAnnulla.Click += (sender, e) =>

{

this.SetResult(Result.Canceled);

this.Finish();

};

Notare che SetResult() imposta il risulato ma non termina l’Activity corrente che dovrà necessariamente essere chiusa tramite finish (concetto di finestra modale). Su activity1 l’evento OnActivityResult viene geenrato soltanto in corrispondenza del finish(). Se Activity2 non esegue il finish ma si limita a riportare Activity1 in primo piano tramite il metodo startActivity( ), l’evento OnActivityResult su Activity1 non viene generato. Lettura del risultato da parte di Activity1

Activity1 infine potrà andare a leggere il risultato ricevuto gestendo il seguente evento relativo all’Activity

OnActivityResult(int requestCode, Result resultCode, Intent intent)

dove:

Il primo parametro rappresenta il codice relativo alla richiesta inviata da Activity1

Il secondo parametro rappresenta il codice restituito da Activity2

Il terzo parametro rappresenta gli eventuali dati inviati da Activity2 ad Activity1

protected override void OnActivityResult(int requestCode, [GeneratedEnum]

Result resultCode, Intent data){

if(requestCode == CODICE_RICHIESTA){

String pulsantePremuto = "";

if(resultCode == Result.Ok)

pulsantePremuto = "RESULT_OK";

else if(resultCode == Result.Canceled)

pulsantePremuto = "RESULT_CANCELED";

String par = null;

if(data!=null && data.HasExtra("risultato"))

par = data.GetStringExtra("risultato");

textView.Text(pulsantePremuto + “ – “ + par); }}

Page 40: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 40

Gestione dei thread

Utilizzo di un thread generico

Per gestire un thread occorre istanziare due oggetti:

un oggetto Runnable che consente di definire una singola procedura all’interno di un thread

separato. Runnable è una classe Astratta la cui istanza deve implementare il metodo Run, che è il metodo che consente di definire la procedura da eseguire in un thread separato. Si tratta di un oggetto Java e bisogna quindi andare ad aggiungere una using Java.Lang;

un oggetto Handler che è un oggetto contenuto nel namespace Android.OS che consente di

controllare il thread definito all’interno di Runnable (avvio / arresto / terminazione).

La procedura invocata all’interno di un thread separato può comunque accedere ai controlli dell’interfaccia grafica.

private Handler threadHandler;

privare static long INTERVALLO = 1000;

public override void OnCreate(Bundle savedInstanceState) {

base.OnCreate(savedInstanceState);

// Set our view from the "main" layout resource

SetContentView(Resource.Layout.activity_main);

threadHandler = new Handler();

}

btnAvvia.Click += (sender, e) => {

// Avvio del thread che verrà avviato fra 1000 ms

// Si aspetta come primo parametro una ISTANZA della classe Runnable

threadHandler.PostDelayed(AggiornaGrafica, INTERVALLO);

};

Terminate le istruzioni da eseguire il thread si arresterebbe. Volendo ottenere una esecuzione ciclica, occorre aggiungere comando di riavvio in modo ricorsivo in coda al thread stesso:

AggiornaGrafica = new Java.Lang.Runnable(() =>

{

txt.Text = “tick”;

threadHandler.PostDelayed(AggiornaGrafica, INTERVALLO);

});

// Arresto del thread

btnArresto.Click += (sender, e) => {

threadHandler.RemoveCallBacks(AggiornaGrafica);

};

Il tutto può essere generato dentro onCreate.

Sleep di un thread

Se si vuole forzare un thread in stato di sleep lo si può fare, ma solo all’interno di thread separati e non in quello principale in quanto si rischierebbe di interrompere anche il refresh grafico della pagina. Abbastanza pericoloso.

Page 41: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 41

La classe Action

Se NON si volesse utilizzare una classe Java si potrebbe far uso di Action che fa parte del namespace System. Anche in questo caso occorre istanziare l’oggetto Handler e Action andrebbe semplicemente a sostituire l’oggetto Runnable. private Handler threadHandler;

privare static long INTERVALLO = 1000;

private Action AggiornaGrafica;

AggiornaGrafica = () => {

txt.Text = “tick”;

threadHandler.PostDelayed(AggiornaGrafica, INTERVALLO);

};

Button btnA = FindViewById(Resource.Id.btnAvvia) as Button;

btnAvvia.Click += (sender, e) => {

threadHandler.PostDelayed(AggiornaGrafica, INTERVALLO);

};

// Problema rimozione in Xamarin

Button btnB = FindViewById(Resource.Id.btnArresta) as Button;

btnB.Click += (sender, e) => {

threadHandler.RemoveCallbacks(AggiornaGrafica);

};

Utilizzando questo metodo si genera però un problema quando si cerca di andare a rimuovere il thread e non si riesce ad effettuare la rimozione. Ancora non sono riuscito a risolvere il problema.

Menù

Ogni applicazione può possedere un menù attraverso il quale è possibile associare delle azioni di interazione con l’activity corrente. Ci sono due tipi di menù: OptionsMenu e ContextMenu.

OptionsMenu

E’ il tipico menù che si apre clickando sui “tre puntini” in alto a destra all’interno della Action Bar (barra del titolo). Gli OptionsMenù sono associati ad una singola Activity ed espongono le operazioni più importanti che un utente può eseguire relativamente a quella Activity. Da Android 5 in avanti le voci vengono visualizzate in verticale una sotto l’altra. Le voci scompaiono automaticamente dopo il click su una delle voci oppure dopo un click sull’area dell’Activity.

Evento OnCreateOptionMenu

All’avvio Android crea automaticamente un menù vuoto per l’Activity corrente. Al termine della fase di avvio richiama automaticamente l’evento OnCreateOptionMenu (callback

method) a cui viene iniettato come parametro il riferimento al menu. Il programmatore può utilizzare questo evento per popolare il menù.

Il metodo restituisce un booleano che indica al SO se deve visualizzare oppure no i “tre puntini” di accesso al menù

return true siginifica che il menù è stato popolato e si chiede al SO di visualizzare i tre puntini di apertura del menù medesimo

Page 42: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 42

return false si chiede al SO di NON visualizzare i tre puntini di apertura del menù che potranno essere eventualmente visualizzati in un altro momento.

In genere però, nel caso in cui il menù non sia stato popolato, non si esegue il return false, ma si

richiama il metodo corrispondente della superclasse per dare al sistema l’opportunità di popolare il menù con eventuali items di sistema.

if (ok) // se il menù è stato popolato

return true;

else

return base.OnCreateOptionsMenu(menu);

Aggiunta di nuove voci tramite il metodo add()

menu.Add(int groupId, int itemId, int order, CharSequence title)

groupId è un parametro che indica il gruppo di appartenenza della voce Menu.None = no group

itemId indica l'id da assegnare alla voce del menù

order specifica la posizione della voce all'interno del menù (Menu.None = ordine naturale).

title specifica la stringa di testo che verrà mostrata all'utente

Esempio: menu.Add(Menu.None, 1, 1, "Voce 1");

menu.Add(Menu.None, 2, 2, "Voce 2");

Il gruppo non ha alcuna funzione visuale, ma serve semplicemente a raggruppare le voci da un punto di vista logico in modo da poter applicare al gruppo i metodi di gruppo tipo SetGroupCheckable, SetGroupEnabled, SetGroupVisible. Accesso all’item e relativi metodi

Il metodo .Add() restituisce un riferimento all’item appena aggiunto. Questo riferimento può essere

utilizzato per aggiungere una icona alla voce oppure, ad esempio per renderla selezionabile tramite un checkbox:

MenuItem item = menu.Add(Menu.None, 3, 3, "voce3"); // oppure

MenuItem item = menu.FindItem(Resource.Id.myId); //item id

MenuItem item = menu.GetItem(0); //item index

Sul singolo item sono disponibilii seguenti metodi:

item.ItemId() // (Property)restitusice l’ID dell’item

item.TitleFormatted.ToString() // restitusice il testo dell’item item.SetIcon(Resource.Drawable.myIcon);

item.SetCheckable(true);

item.SetChecked(true/false);

item.SetEnabled(true/false);

item.SetVisible(true/false);

item.IsChecked() // restitusice true se l’item è selezionato

Il SetCheckable rende la voce selezionabile, ma il check deve essere impostato esplicitamente da

codice in corrispondenza del click. Aggiunta di un Submenu

L’oggetto Submenu consente di aggiungere al menù corrente un sottomenù a cui possono essere applicati tutti gli stessi identici metodi applicabili al menù principale.

Page 43: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 43

SubMenu menu2 = menu.AddSubMenu(Menu.None, 6, 6,"Opzioni");

menu2.add(GRUPPO, 11, 1, "Opzione 1");

menu2.add(GRUPPO, 12, 2, "Opzione 2");

menu2.SetGroupCheckable(GRUPPO, true, false);

Il metodo .SetGroupCheckable consente di rendere selezionabili (con chekbox) tutte le voci del

gruppo. Il secondo parametro se true rende le voci selezionabili.

Il terzo parametro (boolean exclusive), se impostato a true rende le varie voci esclusive,

trasformando di fatto i checkbox in radiobutton (i quadratini dei chekbox diventano cerchi).

Evento OnOptionsItemSelected di risposta al click sulle voci

In corrispondenza del click su una qualunque voce del Menù, viene generato questo evento che riceve come parametro un riferimento all’item che ha generato l’evento.

alert(item.TitleFormatted.ToString());

alert(item.ItemId.ToString());

if (item.IsChecked())

item.SetChecked(false);

else

item.SetChecked(true);

Le ultime due righe consentono di impostare/rimuovere effettivamente il check a seguito del click.

Risultato restituito da OnOptionsItemsSelected

Anche l’evento onOptionsItemSelected dispone di un return finale.

return true. Significa che l’evento è stato consumato dal gestore corrente.

return false L’evento non è stato consumato dal gestore corrente e viene inoltrato ad altri

eventuali gestori che potranno eventualmente gestirlo

Come nel caso precente, se l’evento non è stato consumato, al termine si richiama il metodo corrispondente della superclasse e si ritorna il suo risultato.

int id = item.getItemId();

switch (id) {

case 1: ……… break;

case 2: ……… break;

case 3: ……… break;

default:

return base.OnOptionsItemSelected(item);

}

return true;

Creazione statica di un OptionMenu tramite file xml

Invece di aggiungere dinamicamente le voci, un OptionsMenu può anche essere creato staticamente

aggiungendo all’interno della cartella delle risorse un nuovo file menu.xml.

Creare una nuova sottocartella di nome menu all’interno della cartella Resources, menu / Aggiungi / Nuovo element e selezionare la voce Menu

Viene creato il nuovo file xml. A differenza del layout, all’oggetto menu non è associato un designer, per cui occorre lavorare direttamene sul file xml impostando gli stessi attributi dell’esempio precedente cioè id e title.

Page 44: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 44

<!-- check box -->

<item android:id = "@+id/chkBox"

android:title="voce9"

android:checkable="true"

android:order="100">

</item>

<group android:id = "@+id/gruppo1">

<item android:id = "@+id/item1" android:title="voce1"> </item>

<item android:id = "@+id/item2" android:title="voce2"> </item>

<item android:id = "@+id/item3" android:title="voce3"> </item>

</group>

<!-- radio button -->

<item android:id = "@+id/opzioni" android:title="opzioni">

<menu>

<group android:checkableBehavior="single">

<item android:id = "@+id/opzione1" android:title="opzione1"></item>

<item android:id = "@+id/opzione2" android:title="opzione2"></item>

</group>

</menu>

</item>

L’opzione android:checkableBehavior è l’analogo del metodo .SetGroupCheckable e

consente di applicare l’attributo checkable a tutti gli item di un gruppo senza dover applicare il :checkable ad ogni singolo elemento. I valori possibili sono:

all rende selezionalbili tutti gli elementi del gruppo, visualizzando a fianco di ciascun item un

tipico checkbox single rende selezionalbile un solo elemento alla volta, visualizzando a fianco di ciascun item un

tipico radio button di esclusività none rende gli elementi non selezionabili e a fianco degli item non viene visualizzato nulla.

Impostando il valore android:checkableBehavior=”single” sul gruppo NON bisogna più impostare l’attributo checkable all’interno delle opzioni perché altrimenti prevalgono e ritrasformano gli item in check box. Accesso al file di risorsa tramite l’inflater

L'inflating è il meccanismo che permette di istanziare un'oggetto a partire da un file di risorsa.

All’interno dell’evento OnCreateOptionMenu occorre ‘collegare’ il puntatore menu ricevuto dall’evento

con il menu creato staticamente all’interno del file xml. A tal fine si usa l’oggetto MenuInflater.

public boolean OnCreateOptionsMenu (Menu menu){

MenuInflater.Inflate(Resource.Menu.my_menu, menu);

if(ok)

return true;

else

return base.OnCreateOptionsMenu(menu);

}

Page 45: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 45

Evento di risposta al click

L’evento OnOptionsItemSelected rimane lo stesso identico utilizzato nel caso del menù dinamico.

ContextMenu

Il ContextMenu è simile al menù associato al tasto destro del mouse su un controllo Windows. Il ContextMenu associato ad un elemento compare in corrispondenza del click prolungato (long click) sull'elemento.

Si possono associare ContextMenu defferenti per ogni controllo. La sintassi è la seguente :

public void onCreate() {

this.RegisterForContextMenu(lbl);

this.RegisterForContextMenu(btn);

}

Evento OnCreateOptionMenu

Se un controllo ha associato un ContextMenu, nel momento in cui si esegue un long click sul controllo, viene automaticamente generato l’evento OnCreateContextMenu nel quale è possibile creare dinamicamente il menù da visualizzare. Il menù pertanto può variare a seconda dei contesti Il problema principale legato all’evento OnCreateContextMenu è che, a differenza dell’evento OnCreateOptionMenu che viene richiamato soltanto all’avvio dell’applicazione, quest’evento viene

richiamato ogni volta che si esegue un long click, per cui il menù viene ogni volta ricreato e lo stato delle varie opzioni deve eventualmente essere salvato all’interno di una variabile di programma.

pubiic void OnCreateContextMenu(

IContextMenu menu,

View v,

IContextMenuContextMenuInfo menuInfo) { }

Il 1° parametro è il puntatore al menu a cui appendere le nuove voci Il 2° parametro è un puntatore al controllo che ha scatenato l’evento Il 3° parametro è un puntatore ad eventuali ulteriori informazioni aggiuntive

// per prima cosa si richiama la superclasse

base.onCreateContextMenu(menu, v, menuInfo);

if (v.Id == Resource.Id.lblTitolo)

{

IMenuItem item = menu.Add(Menu.None, 1, 1, "grassetto");

item.SetCheckable(true);

item.SetChecked(grassetto);

}

else if(v.Id == Resource.Id.btn) {

menu.SetHeaderTitle("link disponibili:");

menu.Add(Menu.None, 3, 1,"www.google.com");

menu.Add(Menu.None, 4, 2,"www.vallauri.edu");

}

dove grassetto è una variabile globale booleana che vale :

true se il grassetto è impostato

false se il grassetto non è impostato

Page 46: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 46

Il metodo OpenContextMenu(myControl)

Questo metodo, richiamabile da qualunque sezione di codice, consente di aprire da programma il Context Menù dell’oggetto myControl senza dover eseguire un long click.

Evento OnContextItemSelected(IMenuItem item)

Questo evento viene generato ogni volta che si clicca su una delle voci del menù, esattamente come per gli OptionMenu. Il parametro item rappresenta il puntatore alla voce cliccata.

if(item.ItemId==1){

grassetto=!grassetto;

if(grassetto) lbl.setTypeface(

null, (grassetto)?TypefaceStyle.Bold:TypefaceStyle.Normal);

}

Dopo il click il menu viene distrutto e, in corripondenza del prossimo long-click, viene rigenerato.

Android Device Monitor

DDMS = Dalvik Device Monitor Service è un software che funge da terminale grafico verso l’emulatore dello smartphone. E’ come se ci fosse un computer connesso tramite USB allo smartphone.

Tools / Android / Android Device Monitor

Finestra File Explorer

Consente di accedere al file system dello smatphone. Le cartelle dati a cui l’utente ha accesso in scrittura sono sostanzialmente due:

Data (memoria interna)

SdCard (memory card esterna)

Le apk caricate all’interno dello smartphone sono posizionate nella cartella Data / App

I dati sono invece posizionati all’interno della cartella Data / Data / myApp / files /

Dentro Data / Data si può creare una cartella Music in cui salvare ad esempio files.mp3.

Per creare una nuova cartella si usa il pulsante + in alto destra.

Per caricare i files dentro il device è sufficiente il trascinamento o il pulsante in alto a destra prima del+ Per prelevare un files dal device al desktop c’è un apposito pulsante in alto a destra. Finestra Emulator Control

Consente ad esempio di impostare un valore simulato delle attuali coordinate GPS. Possibile anche dai comandi sul lato destro dell’emulatore.

Le aree di memoria di una app

Sono sostanzialmente tre:

Internal Storage (memoria interna) visibile da Android Device Monitor e suddivisa per app. Contiene i dati specifici delle singole app.

External Storage (memoria esterna o SD Memory) che consente di estendere la memoria interna del dispositivo. Essendo rimuovibile, se si effettua il salvataggio di dati sulla SD, è opportuno che i dati salvati non siano indispensabili per il funzionamento dell'applicazione.

Page 47: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 47

Assets / Row Sono aree di memoria interne all’apk. I dati di queste cartelle sono utilizzabili in sola lettura (essendo interni all’apk non è consentito modificare la loro dimensione) e NON sono accessibili tramite File System del dispositivo. Sono accessibili in sviluppo.

Accesso ai files memorizzati nel Internal Storage

// Accesso a cartella interna che viene cancellata quando si disinstalla

// l’applicazione:

String path = FilesDir.AbsolutePath + "/filename.txt";

string s, testo = "";

using (FileReader reader = new FileReader(path))

{

BufferedReader br = new BufferedReader(reader);

while ((s = br.ReadLine()) != null)

{

testo += s + "\r\n";

}

br.Close();

}

Accesso ai files memorizzati nell’External Storage

Occorre innanzittutto aggiungere all’interno del file Manifest (direttamente nel tag principale

<manifest>) la seguente riga:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> In Visual Studio: Doppio click su Properties e selezionare Android Manifest e quindi aggiungere le permission.

Per recuperare il path abbiamo due possibilità: Questa è la cartella esterna pubblica: non verrà cancellata alla rimozione dell’app: string path = Environment.ExternalStorageDirectory.AbsolutePath;

Questa invece è la cartella esterna privata: verrà cancellata alla rimozione dell’app:

string path2 = GetExternalFilesDir(null).AbsolutePath;

Il path da indicare per l’accesso al file sarà il seguente :

String filePath = "/sdcard/filename.txt";

Dopo di che si possono utilizzare gli stessi metodi dell’Internal Storage

Page 48: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 48

Shared Preferences

Le SharedPreferences vengono salvate all’interno di un’area di memoria comune in cui ogni App può salvare delle variabili in formato chiave/valore, variabili che la App può leggere in qualsiasi momento. Shared nel senso che sono condivise tra tutte le Activity. Ottime per salvare le preferenze dall’utente. Le SharedPreferences vengono salvate in un file xml in the app data folder, i.e.

/data/data/YOUR_PACKAGE_NAME/shared_prefs/YOUR_PREFS_NAME.xml

Il metodo GetSharedPreferences ritorna la Shared Preference indicata dal primo parametro.

Se non esiste la crea. Il secondo parametro è lo stesso di prima ed indica i diritti di accesso. Si usa sempre MODE PRIVATE , i valori READABLE e WRITEABLE sono stati deprecati.

L’oggetto editor consente di modificare le singole variabili di un gruppo di SharedPreferences.

public void btnAggiungiPreferenza(){

ISharedPreferences myPrefs = GetSharedPreferences("Gruppo1",

FileCreationMode.Private);

ISharedPreferencesEditor editor = myPrefs.Edit();

editor.PutString("nome", "pippo");

//! NOME:PIPPO NON É STATO ANCORA CARICATO NELLA MEMORIA PERSISTENTE DEL

// TELEFONO

editor.PutString("cognome", "depippis");

editor.PutInt("eta", 18);

editor.Remove("cognome");

//! editor.Commit(); //Versione per le vecchie API

editor.Apply(); //Scrivere le mie preferenze nella memoria persistente

}

public void btnLeggiPreferenza(){

ISharedPreferences myPrefs = GetSharedPreferences("Gruppo1",

FileCreationMode.Private);

//key della preferenza, default response

string nome = myPrefs.GetString("nome", "Nessun valore"); string

cognome = myPrefs.GetString("cognome", "Nessun valore");

int eta = myPrefs.GetInt("eta", -1);

string message = nome + "\r\n" + cognome + "\r\n" + eta.ToString();

show(message);

SharedPreferences myPrefs=getSharedPreferences("Shared1",MODE_PRIVATE);

String nome = myPrefs.getString("nome", "Nessun valore");

String cognome = myPrefs.getString("cognome", "Nessun valore");

int eta = myPrefs.getInt("eta", 0);

String s = nome + " - " + cognome + " - " + Integer.toString(eta);

// cognome restituisce “nessun valore”;

alert(s);

}

Page 49: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 49

ListView e ArrayAdapter

ArrayAdapter

Per il caricamento dei dati da ArrayList a un Listiew, occorre utilizzare un Adapter che si occupi di associare il dato corretto in relazione al layout grafico definito per la visualizzzione delle singola righe. Si chiama Adapter in quanto funziona proprio come adattatore tra due elementi: i dati e il layout.

Esistono numerose varianti di questi "adattatori" a seconda della natura dei dati da mostrare. Uno dei più usati è l'ArrayAdapter, che permette di gestire i dati memorizzati sotto forma di array.

Al costruttore dell'ArrayAdapter occorre passare: 1. Il contesto corrente 2. il nome del layout da utilizzare per la visualizzazione delle singole righe 3. il nome dell'ArrayList che funge da sorgente dati. Invece di un ArrayList, è possibile passare

direttamente un vettore di stringhe. L’ArrayList però è molto più flessibile.

Istanza dell’Adapter e associazione con la sorgente dati

ArrayAdapter adapter = new ArrayAdapter(this,

Android.Resource.Layout.SimpleSpinnerItem, list);

Android.Resource.Layout.SimpleSpinnerItem è un layout predefinito che permette di gestire

un solo elemento di testo. E’ possibile creare layout personalizzati contenenti la rappresentazione di ogni singola riga tramite la combinazione di più TextView uno per ogni campo del record. Sequenza delle operazioni da eseguire nella mainActivity:

List<Studente> list = new List<Cittadino>();

ArrayAdapter adapter;

ListView lstStudenti;

protected void onCreate() {

caricaLista();

adapter = new ArrayAdapter(this,

Android.Resource.Layout.SimpleSpinnerItem, list);

lstStudenti = FindViewById<ListView>(Resource.Id.lstStudenti);

lstStudenti.Adapter = adapter;

listStudenti. OnItemClickListener = this; // la classe implementa: // AdapterView.IOnItemClickListener

Nota L’oggetto adapter opera soltanto associato ad oggetti come ListView e Spinner ma non ad esempio con un TextView che può contenere un solo elemento.

ListView

Le liste visualizzano i record uno sotto l'altro con la possibilità di effettuare il classico scroll.

Una volta trascinato sul Layout il controllo ListView si possono definire le seguenti proprietà:

android:choiceMode="singleChoice" // Seleziono un solo element alla volta

android:listSelector="blue" // Colore dell’elemento selezionato

android:fastScrollAlwaysVisible="true" // Barra scorrimento sempre visibile

android:fastScrollEnabled="true"

Se non si specifica il listSelector, non viene usato alcun evidenziatore ma semplicemente, al

momento del click, l’elemento selezionato si ricolora per un attimo di blu e poi ritora subito grigio.

Page 50: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 50

Evento OnItemClick

Il metodo di evento OnItemClick si aspetta i seguenti quattro parametri:

parent riferimento al controllo che ha scatenato l’evento (ListView / AdapterView)

view the view within the ListView / AdapterView that was clicked (this will be a view provided

by the adapter). Cioè l’item del ListView che è stato cliccato. position The position of the clicked-view in the adapter.

id The row id of the item that was clicked. ListView.OnItemClickListener listener = new ListView.OnItemClickListener()

{

public void onItemClick(AdapterView<?> parent, View v, int pos, long id)

{

String item = parent.GetItemAtPosition(pos).ToString();

show(item);

}

};

Scroll del List View

lstCitta.SetSelection(2); // La lista viene visualizzata a partire dall’elemento indicato.

Per eseguire lo scroll della ListView è sufficiente clickare su una voce e poi trascinare. Per eseguire lo scroll da codice : lstCitta.SetSelection(index); La lista verrà visualizzata a

partire dall’elemento avente l’indice index (ovviamente a base 0).

La direttiva di layout android:scrollbars= "vertical" è già definita di default.

All’atto del trascinamento compare automaticamente sulla destra una piccola scroll bar,

Spinner

Implementa il tipico Combo Box. Il funzionamento è praticamente identico rispetto al ListView anche se esteticamente meno bello. Occorre definire una sorgente dati di tipo ArrayList ed un apposito adapter. L’evento non è più OnItemClickListener ma OnItemSelectedListener

GridView

Le GridView operano in modo simile rispetto alle ListView. Per la GridView è possibile ripetere lo stesso identico esercizio precedente. I dati del vettore verranno spalmati attraverso le varie colonne.

Dal layout l’unica cosa da definire è il numero di colonne: android:numColumns="3"

E’ anche possibile definire android:numColumns="auto_fit" specificando però columnWidth

Anche la procedura di risposta al click è la stessa identica di cui sopra. La posizione restituita è una posizione vettoriale che si incrementa partendo da 0 e scorrendo le righe. I vari campi dei dati da visualizzare devono però essere caricati sequenzialmente all’interno del vettore.

Creazione di un Adapter personalizzato

Per la visualizzazione di un elenco di dati, in alternativa ad un Layout costruito dinamicamente da codice, è possibile creare tramite Designer un layout personalizzato in cui si definisce la struttura grafica di ogni singolo record che compone l’elenco. Per collegare il layout personalizzato alla sorgente dati occorre ancora definire un adapter personalizzato che funge da Binding tra il layout di visualizzazione e la sorgente dati. In questo modo si definisce la struttura grafica del record tramite Designer senza dover far ricorso alla creazione dinamica con codice java.

Page 51: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 51

Step 1 Definizione di un rowlayout personalizzato

Come layout base di ogni singolo record si può utilizzare un Linear Layout orizzontale avente: larghezza = match_parent altezza = wrap_content

Al suo interno si posizionano tutti i vari widget relativi al record da visualizzare assegnando a ciascuno un apposito ID.

Step 2 Definizione di un Adapter personalizzato per la gestione dei dati

L’Adapter personalizzato può ereditare dalla classe BaseAdapter (Adapter base, occorre però eseguire una implementazione abbastanza complessa) oppure, più semplicemente, può ereditare dalla classe ArrayAdapter<Type> nel qual caso occorre implementare soltanto il metodo

GetView(int position, View layout, ViewGroup parent)

Questo metodo viene richiamato automaticamente nel momento in cui, tramite la property Adapter,

si collega un controllo di visualizzazione al Personal Adapter. In questo momento il Run Time provvede a scorrere una ad una tutte le righe della sorgente dati e, in corrispondenza di ogni riga, provvede a richiamare il metodo GetView() dell’Adapter per aggiungere

la riga all’interno dell’Adapter stesso. NOTA: Il controllo linkato deve assolutamente avere la proprietà layout_height="match_parent"

In caso di wrap_content l’evento viene richiamato più volte per ogni record.

I tre parametri iniettati al metodo GetView rappresentano rispettivamente:

la posizione (all’interno della Sorgente Dati) dell’elemento che si vuole visualizzare sul layout

un riferimento al layout personalizzato per la visualizzazione della riga (che il primo giro è null)

un riferimento al layout genitore (layout principale)

Il metodo ritorna un riferimento al layout personalizzato in modo che, nei giri successivi, il riferimento possa essere passato come secondo parametro al metodo stesso, evitando di re-istanziarlo ogni volta. public class MyAdapter : ArrayAdapter<Studente> {

private MainActivity context;

private int layout_ID;

private List<Studente> list;

private final Context context;

private final int layout;

private final List<Studente> list;

public MyAdapter(Context context, int layout, List<Studente> list) :

base(context, layout, list) {

this.context = context;

this.layout = layout;

this.list = list;

}

public View getView(int position, View layout, ViewGroup parent) {

View v = null;

if (layout == null) {

LayoutInflater inflater = (LayoutInflater)

context.GetSystemService(Context.LayoutInflaterService);

v = inflater.Inflate(Resource.Layout.row_layout, parent, false) as

LinearLayout;

}

Page 52: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 52

else

v = layout;

TextView txtId =(TextView) v.FindViewById(Resource.Id.txtId);

TextView txtNome = (TextView) v.FindViewById(Resource.Id.txtNome);

ImgView img = (ImgView) v.FindViewById(Resource.Id.img);

Studente studente = list[position];

txtId.Text=studente.Id.ToString();

txtNome.Text=studente.Nome;

Resources res = context.getResources();

int imgID=context.Resources.GetIdentifier(studente.Img_path,"drawable",

context.PackageName);

img.SetImageResource(im);

return v;

}

}

L'inflating è il meccanismo che permette di istanziare un'oggetto a partire da una risorsa XML.

La IF serve ad evitare che l’oggetto relativo al rowlayout venga re istanziato ad ogni giro

All’interno degli Adapter personalizzati NON è consentito l’utilizzo dei Toast

Activity Principale

Dichiarazione e istanza dell’Adapter hanno la stessa firma vista per l’Adapter base ma non sono tipizzate

List<Studente> list = new List<Studente>();

ListView lstStudenti;

protected void onCreate() {

caricaLista();

ArrayAdapter adapter = new RecordAdapter(this,

Resource.Layout.record_layout, list);

lstStudenti = FindViewById<ListView>(Resource.Id.lstStudenti);

lstStudenti.Adapter = adapter;

lstStudenti.ItemClick += LstCitta_ItemClick;

private void LstCitta_ItemClick(object sender,

AdapterView.ItemClickEventArgs e)

{

Studente studente=studenti[e.Position];

show(studente.ToString());

}

Pulsanti interni all’Adapter

Su un pulsante definito all’interno di un Adapter è possibile associare in “forma breve” (tramite Designer) un listener definito all’interno dell’Activity principale oppure, in alternativa, è anche possibile definire il listener direttamente all’interno dell’Adapter.

Page 53: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 53

Accesso ad un web service HTTP

Uno dei metodi più comuni utilizzati dalle applicazioni per comunicare con il mondo esterno è quello di accedere tramite HTTP ai web service dedicati dai quali possono scaricare svariati tipi di contenuti

Affinchè la app possa inviare richieste HTTP all’esterno occorre registrare i permessi all’interno del file Manifest, creando una nuova sezione direttamente all’interno del tag<manifest>

<uses-permission android:name="android.permission.INTERNET"/>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

Doppio click su Properties e poi selezionare Android Manifest La classe astratta AsynkTask

L’oggetto AsynkTask è un wrapper di Android che utilizza un oggetto particolare per eseguire una

certa procedura in un thread secondario e gestisce la comunicazione fra il thread principale ed il thread secondario senza costringere il programmatore ad entrare nei dettagli di livello più basso (Messages). La classe AsynkTask è stata pensata appositamente come classe di supporto per l’esecuzione di thread di breve durata che al termine restituisco un risultato al chiamante. Metodi della classe AsyncTask

protected override string RunInBackground(params string[] @params) unico

metodo effettivamente eseguito all’interno di un thread separato. E’ di tipo protected, quindi non visibile all’esterno della classe e può essere richiamato tramite il metodo pubblico Execute(). E’ l’unico metodo ABSTRACT. Gli altri tre metodi sono metodi di evento richiamati rispettivamente in corrispondenza dell’avvio del thread, a tempo durante l’esecuzione del thread, ed in corrispondenza della terminazione del thread.

Il parametro @params è una ellisse, cioè sequenza di parametri tutti dello stesso tipo che il

chiamato tratta come un vettore. Si aspetta un parametro del tipo indicato da TParams e restituisce un risultato di tipo indicato da TResult che viene passato automaticamente all’evento

OnPostExecute

OnPreExeute() richiamato nel momento in cui il thread viene avviato. Per eventuali inizializzazioni

OnProgressUpdate(params Object[] native_values) utilizzato per riportare sulla UI lo stato

di avanzamento del thread. Si aspetta un parametro dei tipo indicato da TProgress che potrebbe essere ad esempio una progress bar di visualizzazione dello stato di avanzamento (sulla base ad es del n. di bytes ricevuti)

OnPostExecute(String result) richiamato al termine dell’esecuzione del thread. Il parametro

result viene iniettato da AsynkTask al termine del metodo RunInBackground (cioè in

corrispondenza del ricevimento dei dati dal server). Scopo di questo evento è quello di elaborare il risultato scrivendolo all’interno di un Object ricevuto dall’Activity principale.

Page 54: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 54

Dichiarazione di una classe che eredita da AsyncTask

La classe astratta AsynkTask è una Typed Class (come ad esempio ArrayList) definita però da tre tipizzazioni:

AsyncTask<TParams, TProgress, TResult>

TParams rappresenta il tipo delle variabili che il chiamante può passare al metodo execute (che a sua

volta richiama RunInBackground). Le variabili devono essere tutte dello stesso tipo e vengono

passate attraverso una ellissi. TParams seve appunto a tipizzare questi parametri. Se non si vogliono passare parametri TParams sarà Void.

TProgress rappresenta un object utilizzabile dal metodo OnProgressUpdate per aggiornare il

thread principale (UI) sullo stato di avanzamento del thread. Normalmente impostato a Missing

TResult rappresenta il tipo del risultato restituito dal metodo RunInBackground che viene

automaticamente passato all’evento OnPostExecute() Esempio di classe che eredita da AysncTask:

public class InviaRichiestaHttp : AsyncTask<string, Missing, string> { }

cioè il metodo RunInBackground dovrà ricevere come parametro un ellisse (sequenza) di stringhe e

dovrà restituire una stringa che verrà automaticamente passata a OnPostExecute.

MainActivity: Istanza della classe ed invo della richiesta

L’activity principale dovrà istanziare la classe InviaRichiestaHttp e richiamare il metodo

Execute che provvede ad attivare il metodo RunInBackground della classe AsynkTask.

InviaRichiestaHttp inviaRichiesta new InviaRichiestaHttp(myParam)

inviaRichiesta.Execute(“get”, "/cercaStudente", "nomeStudente=pippo");

Se TParams viene impostato al valore String, allora il metodo Execute() si aspetta come parametri una ellissi di stringhe. Nel caso ci fosse necessità di passare ad Execute() delle informazioni di tipo diverso da String, questo non è più possibile. Parametri di tipo differente possono però essere passati al costruttore della classe InviaRichiestaHttp, costruttore che provvederà a salvarli all’interno di

appositi campi privati. In questo modo si potrebbe passare anche il context, indispensabile se il

thread deve effettuare un Toast. Passare i parametri ad Execute() oppure al costruttore è assolutamente indifferente. E’ anche possibile passare tutti i parametri al cotruttore senza più passarli ad execute. In tal caso nella dichiarazione della classe tipizzata InviaHttpRequest come primo parametro si può impostare Void e RunInBackground ricevera una ellissi vuota (Void … args).

Se l’unico metodo utilizzato è Execute() non serve nemmeno salvare il riferimento all’interno di una variabile

new InviaRichiestaHttp(myParam).execute(“get”, "/cercaStudente",

"nomeStudente=pippo");

Page 55: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 55

Nota sull’indirizzo IP

Se il server è sulla macchina stessa, come indirizzo ip del server occorre utilizzare l’indirizzo della scheda fisica e NON l’indirizzo della scheda virtuale 127.0.0.1 e nemmeno localhost che è un alias di 127.0.0.1. Entrambi nel caso dell’emulatore puntano all’emulatore stesso che ha un suo indirizzo IP diverso da quello della macchina fisica. Oggetti per l’invio di una richiesta HTTP

All’interno della classe AsyncTask occorre poi utilizzare gli oggetti necesari per gestire l’invio di una richiesta HTTP al server e la ricezione della relativa risposta. Questi oggetti hanno tutti la caratteristica di esporre metodi sincroni, cioè che non restituiscono il controllo fino a quando non ricevono la risposta dal server, per cui devono essere utilizzati all’interno di AsyncTask oppure in fase di inizializzazione (splash screen). La classe DefaultHttpClient è stata deprecata nelle ultime versioni Android. Al suo posto si possono usare varie altre classi, noi ne vedremo un paio: HttpClient: è la classe principale utilizzata per inviare e ricevere messaggi Http. Le sue caratteristiche principali sono:

- configurare le estensioni, impostare le headers predefinite, annullare le richieste e altro - si possono inviare tutte le richieste che si vuole tramite un'unica istanza di HttpClient - non sono associati a un server HTTP o host particolare. Puoi inviare qualsiasi richiesta HTTP,

usando la stessa istanza di HttpClient. - La classe HttpClient utilizza il nuovo standard orientato ai Task per gestire le richieste

asincrone. Pertanto, semplifica la gestione e il coordinamento delle richieste in sospeso.

Passaggi da seguire: Dopo aver creato il progetto va aggiunto un pacchetto NuGet (Gestione pacchetti NuGet per la soluzione):

Quindi fare click DX sul progetto e selezionare “Aggiungi riferimento…” e selezionare la voce System.Net.Http e fare Ok:

Page 56: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 56

A questo punto si può procedere con la programmazione

class InviaRichiestaHttp : AsyncTask<string, Missing, string>

View v;

MainActivity content;

public InviaRichiestaHttp(View v, MainActivity content)

{

this.v = v;

this.content = content;

}

protected override string RunInBackground(params string[] @params)

{

string metodo = @params[0];

string risorsa = @params[1];

string parametro = @params[2];

string urlString = "http://10.0.0.106:1337";

UTF8Encoding encoding = new UTF8Encoding();

urlString += risorsa;

using (var client = new HttpClient())

{

if (metodo == "get")

{

urlString += "?nomeInserito=" + parametro;

// send a GET request

Page 57: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 57

using (var response = client.GetAsync(urlString).Result)

{

if (response.IsSuccessStatusCode)

{

s = response.Content.ReadAsStringAsync().Result;

}

}

}

else

{

var content = new StringContent(

"nomeInserito=" + parametro, Encoding.UTF8);

var postResponse = client.PostAsync(urlString, content);

// on error throw a exception

postResponse.Result.EnsureSuccessStatusCode();

if (postResponse.IsCompletedSuccessfully)

s = postResponse.Result.Content.ReadAsStringAsync().Result;

}

}

return s;

}

protected override void OnPostExecute(string result)

{

TextView txt = (TextView)v;

txt.Text = result;

}

URI e URL sono quasi sinonimi. URI è più generico in quanto è applicabile anche alla definizione delle risorse tramite namespace.

Soluzione 2: La classe HttpURLConnection (più semplice)

Questa seconda soluzione ha il pregio di non distinguere sostanzialmente fra richieste GET e POST, entrambe inviate tramite il comando conn.Connet();.

In caso di parametri post è sufficiente aggiungerli alla connessione dopo averla aperta.

La property conn.DoOutput=true; abilita la scrittura di dati sull connessione e trasforma la

chiamata da GET a POST

Page 58: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 58

protected override string RunInBackground(params string[] @params)

{

string metodo = @params[0];

string risorsa = @params[1];

string parametro = @params[2];

string urlString = "http://10.0.0.106:1337";

UTF8Encoding encoding = new UTF8Encoding();

urlString += risorsa;

string s="";

//? ***** VERSIONE 2 *************************

//

//? HttpURLConnection sia GET che POST

//? ********************************************

URL url;

HttpURLConnection connection;

StreamReader resStream;

if (metodo == "get")

{

urlString += "?nomeInserito=" + parametro;

url = new URL(urlString);

connection = (HttpURLConnection)url.OpenConnection();

connection.RequestMethod = "GET";

connection.DoInput = true;

connection.ConnectTimeout = 2000;

connection.Connect();

}

else

{

url = new URL(urlString);

connection = (HttpURLConnection)url.OpenConnection();

connection.RequestMethod = "POST";

connection.DoOutput = true;

connection.DoInput = true;

connection.ConnectTimeout = 2000;

// Inserimento parametric in post

StreamWriter sw = new StreamWriter(connection.OutputStream,

Encoding.ASCII);

string data = "";

data = "nomeInserito=" + Uri.Encode(parametro);

sw.Write(data);

sw.Flush();

sw.Close();

//Dopo la Close va fatta subito la Connect,

//altre impostazioni vanno in errore

connection.Connect();

} // Lettura risposta

resStream = new StreamReader(connection.InputStream, encoding);

s = resStream.ReadToEnd();

resStream.Close();

return s;

}

Page 59: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 59

Gestione di uno stream jSon

ATTENZIONE: dalla versione di Android 9 “Pie” le chiamate http in chiaro vengono, di default bloccate dal S.O. Per evitare il blocco bisogna inserire, all’interno del file Properies -> AssemblyInfo.cs la seguente riga di codice: [assembly: Application(UsesCleartextTraffic = true)]

Ovviamente, ciò non è necessario se andiamo ad effettuare delle chiamate in Https Il metodo OnPostExecure riceve solitamente una stringa JSON che dovrà provvedere a parsificare andando poi a visualizzare le varie informazioni sull’interfaccia grafica.

L’oggetto fondamentale per parsificare una stringa JSON è

Newtonsoft.Json.JsonConvert (Anche per questa soluzione bisogna includere

Il pacchetto NuGet Newtonsoft.Json)

Tramite il metodo DeserializeObject<T>(String) abbiamo la possibilità di parsificare

(deserializzare) una stringa JSON in un oggetto T. Qui si aprono 2 possibilità:

1) Creare una classe che rispecchia le caratteristiche del JSON. In questo caso i valori presenti nel JSON verranno iniettati direttamente nella nostra classe creando un oggetto già valorizzato:

Dato il seguente JSON:

{"nome": "Pippo","cognome": "pluto"}

Si va a creare una classe del tipo:

class jsonObj

{

public string cognome { get; set; }

public string nome { get; set; }

}

protected override void OnPostExecute(string result)

{

jsonObj json = JsonConvert.DeserializeObject<jsonObj>(result);

TextView txt = (TextView)v;

txt.Text = "Nome: "+json.nome+" - Cognome: "+json.cognome;

}

2) Un altro metodo è invece quello di utilizzare i dynamic. Bisogna però fare attenzione, perché sembra che non funzionino su iOS in quanto il kernel di iOS impedisce a un’applicazione di generare codice in modo dinamico, come appunto avviene in questo caso. Dato lo stesso JSON non è necessario creare alcuna classe di appoggio e si può procedere nel seguente modo: protected override void OnPostExecute(string result)

{

Page 60: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 60

var json = JsonConvert.DeserializeObject<dynamic>(result);

TextView txt = (TextView)v;

txt.Text = "Nome: "+ json["nome"]+" - Cognome: "+ json["cognome"]; }

Perché utilizzare questa soluzione? Le applicazioni interagiscono sempre più con servizi di terze parti, diventa sempre più importante avere un facile accesso a tali servizi con un semplice parsing JSON. A volte ha molto senso estrarre solo una piccola quantità di dati dal documento JSON ricevuto da un servizio, perché molte volte il servizio di terze parti non è direttamente correlato alla logica dell'applicazione e ha poco senso mappare l'intera struttura del servizio nella propria applicazione.

Richiesta di una immagine al server

Il SetImageURI accetta solo URI locali, quindi, per inserire un’immagine in un widget dobbiamo

prima scaricarlo e poi possiamo associarlo al nostro widget. Per scarciare l’immagine si utilizzano alcuni metodi che possono essere utilizzati all’interno del RunInBackground (eseguito in un thread separato) andando ad utilizzare la proprietà Result che risulta essere bloccante, ma qui non è un problema:

using (var client = new HttpClient())

{

if (metodo == "get")

{

urlString += parametri;

// send a GET request

// .Result rende il metodo bloccante

// nella RunInBackground questo non è un problema e

// ci risparmia vari async e await

// Inoltre .Result aggrega un eventuale eccezzione in

// una AggregateException; con await invece viene ritornata

// l'eccezione così com'è

using (var response = client.GetAsync(urlString).Result)

{

if (response.IsSuccessStatusCode)

{

json = response.Content.ReadAsStringAsync().Result;

}

}

Risultato ris = JsonConvert.DeserializeObject<Risultato>(json);

using (var msg =

client.GetAsync(ris.results[0].picture.large).Result)

{

if (msg.IsSuccessStatusCode)

{

using (var stream =

msg.Content.ReadAsStreamAsync().Result)

{

bm =

BitmapFactory.DecodeStreamAsync(stream).Result;

Page 61: Sommariorobertomana.altervista.org/wp-content/uploads/2020/01/Xa... · 2020-01-11 · ConstraintLayout ... Il 12 novembre 2007 l'OHA ha rilasciato il software development kit SDK

Tecnologie - Classe Quinta prof. Diego Belliardo

Xamarin

pag 61

}

}

}

}

else

{ }

}

Se invece, volessimo/dovessimo scaricare l’immagine al di fuori del RunInBackgroud dovremmo allora andare a fare delle chiamate NON bloccanti tramite l’utilizzo dei costrutti async e await: protected override void OnPostExecute(string result)

{

Risultato ris = JsonConvert.DeserializeObject<Risultato>(result);

show(ris.results[0].ToString());

setImageAsync(ris.results[0].picture.large);

}

private async void setImageAsync(string image)

{

using (var bm = await GetImageFromUrl(image))

imgUtente.SetImageBitmap(bm);

}

private async Task<Bitmap> GetImageFromUrl(string url)

{

using (var client = new HttpClient())

{

var msg = await client.GetAsync(url);

if (msg.IsSuccessStatusCode)

{

using (var stream = await msg.Content.ReadAsStreamAsync())

{

var bitmap = await

BitmapFactory.DecodeStreamAsync(stream);

return bitmap;

}

}

}

return null;

}