Salvare le ricette della nonna con Xamarin.Forms

Pubblicato: 2022-03-10
Riepilogo rapido ↬ Quando si creano app mobili, è necessario creare e mantenere l'interfaccia utente e la logica dell'app sia per iOS che per Android separatamente: Objective-C/Swift con XCode e Java con Android Studio. Questo può trasformarsi rapidamente in un dolore. Con Xamarin.Forms, tuttavia, l'interfaccia utente e la logica dell'app per la tua app risiedono in un'unica base di codice e puoi usare un unico IDE per mantenerlo tutto, risparmiando tempo e mal di testa. In questo articolo, fai un giro in Xamarin.Forms per vedere cosa può fare per te.

Mia nonna prepara i panini migliori, più soffici e deboli che qualcuno abbia mai assaggiato. Il problema è che ci sono un sacco di ingredienti segreti (e non sto solo parlando di amore) che entrano in quei panini, e quegli ingredienti e quelle indicazioni sono tutti immagazzinati nella testa di mia nonna.

Tutti abbiamo ricette di famiglia del genere e, invece di dimenticarle, in questo articolo creeremo un'app mobile per iOS e Android usando Xamarin.Forms che le salverà per me e per le future generazioni della mia famiglia!

Disegno dei panini con lievitazione a vapore
Deliziosi panini caldi (Grande anteprima)

Quindi, se sei interessato a scrivere applicazioni mobili, ma non hai il tempo di scrivere la stessa app più e più volte per ogni piattaforma, questo articolo è per te! Non preoccuparti se non conosci C# da un'insalata di pretzel alla fragola; Scrivo app Xamarin da oltre 8 anni e questo articolo è un tour di Xamarin.Forms che intende fornirti informazioni sufficienti per iniziare a imparare da solo.

Cos'è questa roba Xamarin?

Più che una semplice parola divertente da dire, Xamarin consente agli sviluppatori di creare applicazioni iOS e Android native utilizzando esattamente gli stessi SDK e controlli dell'interfaccia utente disponibili in Swift e XCode per iOS o Java e Android Studio per Android.

Altro dopo il salto! Continua a leggere sotto ↓
Disegno di una figura stilizzata chiedendosi se dovrebbero svilupparsi per iOS o Android
Per quale piattaforma dovrei sviluppare? (Grande anteprima)

La differenza è che le app vengono sviluppate con C# usando .NET Framework e Visual Studio o Visual Studio per Mac. Le app che ne risultano, tuttavia, sono esattamente le stesse. Sembrano, si sentono e si comportano proprio come le app native scritte in Objective-C, Swift o Java.

Xamarin brilla quando si tratta di condivisione del codice. Uno sviluppatore può creare e personalizzare la propria interfaccia utente per ogni piattaforma usando controlli e SDK nativi, ma poi scrivere una libreria di logica dell'app condivisa condivisa tra le piattaforme.

Disegno di una figura stilizzata con l'idea di sviluppare contemporaneamente per entrambe le piattaforme utilizzando Xamarin
Ah! Sceglierò Xamarin! (Grande anteprima)

È questa condivisione del codice in cui è possibile realizzare enormi risparmi di tempo.

E come i deliziosi panini che prepara mia nonna, una volta dato il gusto di condividere il codice - è difficile non desiderarne di più - ed è qui che entra in gioco Xamarin.Forms.

Xamarin.Forms

Xamarin.Forms prende il concetto di sviluppo Xamarin tradizionale e aggiunge un livello di astrazione.

Invece di sviluppare separatamente l'interfaccia utente per iOS e Android, Xamarin.Forms introduce un toolkit dell'interfaccia utente che consente di scrivere app mobili native da un'unica base di codice.

Pensala in questo modo: hai un'app che ha bisogno di un pulsante. Ogni piattaforma ha il concetto di pulsante. Perché dovresti scrivere l'interfaccia utente un sacco di volte quando sai che tutto ciò che l'utente della tua app deve fare è toccare un pulsante?

Questo è uno dei problemi risolti da Xamarin.Forms.

Fornisce un toolkit dei controlli più comunemente utilizzati e degli eventi di interazione dell'utente per loro, quindi dobbiamo scrivere le interfacce utente per le nostre app solo una volta. Vale la pena notare, tuttavia, che non sei limitato ai controlli forniti da Xamarin.Forms: puoi comunque usare i controlli trovati solo in una singola piattaforma all'interno di un'app Xamarin.Forms. Inoltre, possiamo condividere la logica dell'applicazione tra le piattaforme come prima.

Le statistiche di condivisione del codice per le app sviluppate con Xamarin.Forms possono essere fuori scala. Un'app per l'organizzazione di conferenze ha il 93% del suo codice condiviso su iOS e il 91% su Android. L'app è open source. Dai un'occhiata al codice.

Xamarin.Forms offre più dei controlli dell'interfaccia utente. Contiene anche un framework MVVM, un servizio di messaggistica pub/sub, un'API di animazione e un servizio di dipendenza, oltre ad altri.

Ma oggi ci concentreremo sulle funzionalità dell'interfaccia utente per la creazione della nostra app di gestione delle ricette.

L'app che creeremo

L'app di gestione delle ricette avrà un'interfaccia utente semplice. Lavoreremo in cucina, quindi deve essere facile da usare!

Sarà composto da 3 schermate . Il primo mostrerà un elenco di tutte le ricette attualmente caricate nell'app.

Screenshot della schermata dell'elenco delle ricette su iOS
(Grande anteprima)

Quindi, toccando una di quelle ricette, potrai vederne i dettagli su una seconda schermata:

Screenshot della schermata dei dettagli della ricetta su iOS
La schermata dei dettagli della ricetta su iOS (Anteprima grande)

Da lì puoi toccare un pulsante di modifica per apportare modifiche alla ricetta nella terza schermata:

Screenshot della schermata di modifica della ricetta su iOS
La schermata di modifica della ricetta su iOS (anteprima grande)

Puoi anche accedere a questa schermata toccando il pulsante Aggiungi dalla schermata dell'elenco delle ricette.

L'ambiente di sviluppo

Le app Xamarin vengono compilate con C# e .NET, usando Visual Studio in Windows o Visual Studio per Mac nel Mac, ma è necessario che siano installati anche gli SDK e gli strumenti iOS o Android. Installare tutto nell'ordine corretto potrebbe essere un po' un problema, tuttavia, i programmi di installazione di Visual Studio si occuperanno solo dell'installazione dell'IDE, ma anche degli strumenti della piattaforma.

Sebbene sia sempre necessario un Mac per creare app iOS, con Xamarin puoi comunque sviluppare ed eseguire il debug di tali app da Visual Studio in Windows! Quindi, se Windows è la tua marmellata, non è necessario modificare del tutto i tuoi ambienti.

Ora vediamo come Xamarin.Forms può aiutarci a salvare alcune ricette di famiglia da una base di codice.

Pagina elenco ricette: struttura dell'interfaccia utente

Iniziamo parlando di come layout dell'interfaccia utente per la nostra app di salvataggio delle ricette!

Nel complesso, ogni schermata in Xamarin.Forms è composta da 3 elementi. Una Page . Almeno un elemento chiamato Layout . E almeno un Control .

La pagina

La Pagina è la cosa che ospita tutto ciò che viene visualizzato sullo schermo in una volta. La Page è anche centrale nella navigazione all'interno di un'app.

Disegno che rappresenta una pagina in Xamarin.Forms
La pagina (Anteprima grande)

Diciamo a Xamarin.Forms quale Page visualizzare tramite un servizio di navigazione . Quel servizio si occuperà quindi di visualizzare qualsiasi pagina in un modo appropriato e nativo per il sistema operativo.

In altre parole, anche il codice per navigare tra le schermate è stato astratto!

Infine, sebbene non sia l'unico modo per farlo, codifico l'interfaccia utente delle mie Page in XAML. (L'altro modo sarebbe usare C#.) XAML è un linguaggio di markup che descrive l'aspetto di una pagina. E per ora, basti dire, è un po' simile all'HTML.

Lo schema

Tutti i controlli su una pagina sono organizzati da qualcosa chiamato Layout.

Disegno che rappresenta alcuni layout in Xamarin.Forms
I layout (Anteprima grande)

È possibile aggiungere uno o più layout a una pagina.

Disegno di come i layout interagiscono con la pagina
Layout sulla pagina (Anteprima grande)

Esistono diversi tipi di layout nei moduli. Alcuni dei più comuni includono i layout Stack, Absolute, Relative, Grid, Scroll e Flex.

Disegno di diversi layout di Xamarin.Forms e come dispongono gli elementi figlio.
Layout comuni di Xamarin.Forms (anteprima grande)

I controlli

Poi finalmente ci sono i controlli. Questi sono i widget della tua app con cui l'utente interagisce.

Disegno di un paio di controlli Xamarin.Forms, ciascuno disegnato come una casella
Alcuni dei controlli (Anteprima grande)

I moduli sono dotati di molti controlli che verranno utilizzati indipendentemente dal tipo di app che stai creando. Cose come etichette, pulsanti, caselle di immissione, immagini e, naturalmente, visualizzazioni elenco.

Quando aggiungi un controllo a una schermata, lo aggiungi a un layout. È il layout che si occupa di capire dove esattamente sullo schermo dovrebbe apparire il controllo.

Disegno di una pagina contenente 2 layout e quei layout che dispongono i controlli in base al tipo di layout.
Tutto combacia! (Grande anteprima)

Quindi per generare le seguenti schermate rispettivamente su iOS e Android:

Screenshot della schermata dell'elenco delle ricette su iOS e Android
Elenchi di ricette su iOS (a sinistra) e Android (a destra) (Anteprima grande)

Ho usato questo XAML:

 <?xml version="1.0" encoding="UTF-8"?> <ContentPage xmlns="https://xamarin.com/schemas/2014/forms" xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml" x:Class="SmashingRecipe.RecipeListPage" Title="Recipes"> <ContentPage.Content> <StackLayout> <ListView x:Name="recipesList"> <ListView.ItemTemplate> <DataTemplate> <TextCell Text="{Binding Name}"/> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage.Content> <ContentPage.ToolbarItems> <ToolbarItem Text="Add" /> </ContentPage.ToolbarItems> </ContentPage>

Ci sono un paio di cose importanti che accadono qui.

Il primo è <StackLayout> . Questo sta dicendo a Forms di organizzare tutti i controlli che seguono in uno stack.

Capita che ci sia un solo controllo nel layout, e questo è un <ListView> , e gli daremo un nome in modo da poterlo fare riferimento in seguito.

Poi c'è un po' di cerimonia standard per ListView prima di arrivare a ciò che stiamo cercando: il <TextCell> . Questo sta dicendo a Forms di visualizzare il testo semplice in ogni cella dell'elenco.

Diciamo a <TextCell> il testo che vogliamo che visualizzi attraverso una tecnica chiamata Data Binding . La sintassi è simile a Text="{Binding Name}" . Dove Name è una proprietà di una classe Recipe che modella... beh, Ricette.

Quindi, come vengono aggiunte le ricette all'elenco?

Insieme a ogni file XAML, c'è un file "code-behind". Questo code-behind ci consente di eseguire operazioni come gestire gli eventi di interazione dell'utente, eseguire la configurazione o eseguire altre logiche dell'app.

C'è una funzione che può essere sovrascritta in ogni Page chiamata OnAppearing - che come sono sicuro che hai intuito - viene chiamata quando viene visualizzata la Page .

 protected override void OnAppearing() { base.OnAppearing(); recipesList.ItemsSource = null; recipesList.ItemsSource = App.AllRecipes; }

Notare le recipesList.ItemsSource = AllRecipes;

Questo sta dicendo a ListView : "Ehi! Tutti i tuoi dati si trovano App.AllRecipes (una variabile a livello di applicazione) e puoi utilizzare una qualsiasi delle proprietà del suo oggetto figlio per associare!

Un elenco di ricette va bene, ma non puoi cuocere nulla senza prima vedere i dettagli della ricetta e di questo ci occuperemo in seguito.

Gestione degli eventi

Senza rispondere ai tocchi dell'utente, la nostra app non è altro che un elenco di deliziose ricette dal suono. Suonano bene, ma senza saperli cucinare non serve a molto!

Facciamo in modo che ogni cella in ListView risponda ai tocchi in modo da poter vedere come realizzare la ricetta!

Nel file code-behind RecipeListPage , possiamo aggiungere gestori di eventi ai controlli per ascoltare e reagire agli eventi di interazione dell'utente.

Gestione degli eventi di tocco nella visualizzazione elenco, quindi:

 recipesList.ItemSelected += async (sender, eventArgs) => { if (eventArgs.SelectedItem != null) { var detailPage = new RecipeDetailPage(eventArgs.SelectedItem as Recipe); await Navigation.PushAsync(detailPage); recipesList.SelectedItem = null; } };

Ci sono cose belle che stanno succedendo lì.

Ogni volta che qualcuno seleziona una riga, ItemSelected viene attivato su ListView .

Degli argomenti che vengono passati al gestore, l'oggetto eventArgs ha una proprietà SelectedItem che è qualsiasi cosa sia associata a ListView da prima.

Nel nostro caso, questa è la classe Recipe . (Quindi non dobbiamo cercare l'oggetto nella sorgente principale - ci viene passato.)

Pagina dei dettagli della ricetta

Naturalmente, c'è una pagina che ci mostra gli ingredienti segreti e le indicazioni su come realizzare ogni ricetta, ma come viene visualizzata quella pagina?

Disegno di una figura stilizzata vestita da chef pronto per iniziare a cuocere.
Andiamo a cucinare! (Grande anteprima)

Si noti l' await Navigation.PushAsync(detailPage); linea dall'alto. L'oggetto Navigation è un oggetto indipendente dalla piattaforma che gestisce le transizioni di pagina in modo nativo per ciascuna piattaforma.

Ora diamo un'occhiata alla pagina dei dettagli della ricetta:

Screenshot della schermata dei dettagli della ricetta su iOS e Android
Schermate dei dettagli della ricetta su iOS (a sinistra) e Android (a destra) (Anteprima grande)

Anche questa pagina è stata creata con XAML. Tuttavia, il Layout utilizzato (FlexLayout) è piuttosto interessante poiché è ispirato al CSS Flexbox.

 <ContentPage.Content> <ScrollView> <FlexLayout AlignItems="Start" AlignContent="Start" Wrap="Wrap"> <Image Source="buns.png" FlexLayout.Basis="100%" /> <Label Text="{Binding Name}" HorizontalTextAlignment="Center" TextColor="#01487E" FontAttributes="Bold" FontSize="Large" Margin="10, 10" /> <BoxView FlexLayout.Basis="100%" HeightRequest="0" /> <Label Text="Ingredients" FontAttributes="Bold" FontSize="Medium" TextColor="#EE3F60" Margin="10,10" HorizontalOptions="FillAndExpand" /> <BoxView FlexLayout.Basis="100%" HeightRequest="0" /> <Label Text="{Binding Ingredients}" Margin="10,10" FontSize="Small" /> <BoxView FlexLayout.Basis="100%" HeightRequest="0" /> <Label Text="Directions" FontAttributes="Bold" FontSize="Medium" TextColor="#EE3F60" Margin="10,10" HorizontalOptions="FillAndExpand" /> <BoxView FlexLayout.Basis="100%" HeightRequest="0" /> <Label Text="{Binding Directions}" Margin="10,10" FontSize="Small" /> </FlexLayout> </ScrollView> </ContentPage.Content>

FlexLayout organizzerà i suoi controlli in righe o colonne. Il grande vantaggio viene però dal fatto che può rilevare automaticamente quanto spazio è rimasto sullo schermo per posizionare un controllo e, se non ce n'è abbastanza, può creare automaticamente una nuova riga o colonna per adattarlo!

Questo aiuta molto quando si ha a che fare con schermi di varie dimensioni, che sono molte nello sviluppo mobile.

Bene, con FlexLayout che ci aiuta a mantenere la schermata dei dettagli in buone condizioni, dobbiamo ancora modificare quelle ricette, giusto?

Probabilmente avrai notato questo:

 <ToolbarItem Text="Edit" Clicked="Edit_Clicked" />

Quella riga è responsabile dell'inserimento di un pulsante nella barra degli strumenti dell'app. Clicked="Edit_Clicked" dice al pulsante che quando viene cliccato, cerca nel codice dietro una funzione con quel nome, quindi esegui il suo codice.

Che in questo caso sarebbe istanziare la Pagina di modifica della ricetta e spingerla nel nostro stack di navigazione utilizzando l'oggetto Navigation menzionato in precedenza.

Pagina Modifica Ricetta

Una pagina con un elenco di ricette: controlla! Una pagina con tutti i dettagli per realizzare le ricette: controlla! Non resta che creare la pagina che utilizziamo per inserire o modificare una ricetta mentre guardiamo la nonna fare la sua magia!

Per prima cosa, controlla le schermate:

Screenshot della schermata di modifica della ricetta su iOS e Android
Schermate di modifica delle ricette su iOS (sinistra) e Android (destra) (Anteprima grande)

E ora il codice:

 <ContentPage.Content> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TableView Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Intent="Form" HasUnevenRows="true"> <TableSection Title="General"> <EntryCell x:Name="recipeNameCell" Label="Name" /> </TableSection> <TableSection Title="Ingredients"> <ViewCell> <StackLayout Padding="15"> <Editor x:Name="ingredientsCell" /> </StackLayout> </ViewCell> </TableSection> <TableSection Title="Directions"> <ViewCell> <StackLayout Padding="15"> <Editor x:Name="directionsCell" /> </StackLayout> </ViewCell> </TableSection> </TableView> <Button Text="Save" Grid.Row="1" Grid.Column="0" BackgroundColor="#EE3F60" TextColor="White" x:Name="saveButton" /> <Button Text="Cancel" Grid.Row="1" Grid.Column="1" BackgroundColor="#4CC7F2" TextColor="White" x:Name="cancelButton" /> </Grid> </ContentPage.Content>

C'è un po' più di codice qui, ed è perché sto usando il layout Grid per specificare come tutto dovrebbe essere disposto in uno schema bidimensionale.

E anche qui non si notano dati vincolanti. Perché volevo fornire un esempio di come si possano popolare i controlli esclusivamente dal codice dietro il file:

 void InitializePage() { Title = TheRecipe.Name ?? "New Recipe"; recipeNameCell.Text = TheRecipe.Name; ingredientsCell.Text = TheRecipe.Ingredients; directionsCell.Text = TheRecipe.Directions; saveButton.Clicked += async (sender, args) => { SaveRecipe(); await CloseWindow(); }; cancelButton.Clicked += async (sender, args) => { await CloseWindow(); }; }

Vedi quella proprietà TheRecipe ? È a livello di pagina, contiene tutti i dati per una particolare ricetta e viene impostato nel costruttore della pagina.

In secondo luogo, i gestori di eventi Clicked per saveButton e cancelButton sono totalmente .NET-ified (e sì, mi invento abbastanza spesso le mie parole).

Dico che sono .NET-ified perché la sintassi per gestire quell'evento non è nativa per Java né Objective-C. Quando l'app viene eseguita su Android o iOS, il comportamento sarà esattamente come un clic Android o un TouchUpInside iOS.

E come puoi vedere, ciascuno di quei gestori di eventi di clic sta invocando funzioni appropriate che salvano la ricetta e ignorano la pagina, o semplicemente eliminano la pagina.

Eccolo: abbiamo l'interfaccia utente in basso per salvare le ricette da ora fino alla fine dei tempi!

CSS Cosa?!? O rendere l'app carina

Salvare il meglio per ultimo: Xamarin.Forms 3.0 ci offre, tra le altre cose, la possibilità di applicare uno stile ai controlli usando CSS!

Il CSS di Xamarin.Forms non è al 100% ciò a cui potresti essere abituato dallo sviluppo Web. Ma è abbastanza vicino che chiunque abbia familiarità con i CSS si sentirà come a casa. Proprio come me dalla nonna!

Prendiamo quindi la pagina dei dettagli della ricetta e la rifattorizziamo, in modo che utilizzi i fogli di stile a cascata per impostare gli elementi visivi invece di impostare tutto direttamente in linea nell'XAML.

Il primo passo è creare il documento CSS! In questo caso sarà simile al seguente:

 .flexContent { align-items: flex-start; align-content: flex-start; flex-wrap: wrap; } image { flex-basis: 100%; } .spacer { flex-basis: 100%; height: 0; } .foodHeader { font-size: large; font-weight: bold; color: #01487E; margin: 10 10; } .dataLabel { font-size: medium; font-weight: bold; color: #EE3F60; margin: 10 10; } .data { font-size: small; margin: 10 10; }

Per la maggior parte, sembra CSS. Ci sono classi lì dentro. Esiste un unico selettore per un tipo di classe, Image . E poi un gruppo di regolatori di proprietà.

Alcuni di questi setter di proprietà, ad esempio flex-wrap o flex-basis sono specifici di Xamarin.Forms. Andando avanti, il team prefiggerà quelli con xf- per seguire le pratiche standard.

Il prossimo passo sarà applicarlo ai controlli XAML.

 <ContentPage.Resources> <StyleSheet Source="../Styles/RecipeDetailStyle.css" /> </ContentPage.Resources> <ContentPage.Content> <ScrollView> <FlexLayout StyleClass="flexContent"> <Image Source="buns.png" /> <Label Text="{Binding Name}" StyleClass="foodHeader" /> <BoxView StyleClass="spacer" /> <Label Text="Ingredients" StyleClass="dataLabel" HorizontalOptions="FillAndExpand" /> <BoxView StyleClass="spacer" /> <Label Text="{Binding Ingredients}" StyleClass="data" /> <BoxView StyleClass="spacer" /> <Label Text="Directions" StyleClass="dataLabel" HorizontalOptions="FillAndExpand" /> <BoxView StyleClass="spacer" /> <Label Text="{Binding Directions}" StyleClass="data" /> </FlexLayout> </ScrollView> </ContentPage.Content>

Ecco com'era prima.

In Xamarin.Forms, per fare riferimento al documento CSS, aggiungi un <StyleSheet Source="YOUR DOC PATH" /> . Quindi puoi fare riferimento alle classi in ogni controllo tramite la proprietà StyleClass .

Pulisce definitivamente l'XAML e rende anche più chiara l'intenzione del controllo. Ad esempio, ora è abbastanza ovvio cosa stanno facendo quei <BoxView StyleClass="spacer" /> !

E l' Image ha lo stile stesso perché è Image e il modo in cui abbiamo definito il selettore nel CSS.

A dire il vero, CSS in Xamarin.Forms non è completamente implementato come il suo cugino Web, ma è comunque piuttosto interessante. Hai selettori, classi, puoi impostare proprietà e, naturalmente, tutta quella cosa a cascata in corso!

Sommario

Tre schermate, due piattaforme, un articolo e infinite ricette salvate! E sai cos'altro? Puoi creare app con Xamarin.Forms per più di Android e iOS. Puoi creare piattaforme UWP, macOS e persino Samsung Tizen!

Disegno dei panini con lievitazione a vapore
Delizioso! (Grande anteprima)

Xamarin.Forms è un toolkit dell'interfaccia utente che consente di creare app scrivendo l'interfaccia utente una volta e facendo eseguire il rendering dell'interfaccia utente in modo nativo sulle principali piattaforme.

Lo fa fornendo un SDK che è un'astrazione per i controlli più comunemente usati sulle piattaforme. Oltre alla bontà dell'interfaccia utente, Xamarin.Forms fornisce anche un framework MVVM completo, un servizio di messaggistica pub/sub, un'API di animazione e un servizio di dipendenza.

Xamarin.Forms offre anche tutti gli stessi vantaggi del codice offerti dallo sviluppo Xamarin tradizionale. Qualsiasi logica applicativa è condivisa su tutte le piattaforme. E puoi sviluppare tutte le tue app con un unico IDE usando un unico linguaggio: è davvero fantastico!

Dove andare? Scarica il codice sorgente per questa app Xamarin.Forms per provarla tu stesso. Quindi, per saperne di più su Xamarin.Forms, inclusa la possibilità di creare un'app all'interno del tuo browser, dai un'occhiata a questo tutorial online!