Enregistrer les recettes de grand-mère avec Xamarin.Forms

Publié: 2022-03-10
Résumé rapide ↬ Lors de la création d'applications mobiles, vous devez créer et gérer séparément l'interface utilisateur et la logique d'application pour iOS et Android : Objective-C/Swift avec XCode et Java avec Android Studio. Cela peut rapidement se transformer en douleur. Avec Xamarin.Forms, cependant, la logique de l'interface utilisateur et de l'application pour votre application réside dans une seule base de code et vous pouvez utiliser un seul IDE pour tout gérer, ce qui vous fait gagner du temps et des maux de tête. Dans cet article, faites un tour autour de Xamarin.Forms pour voir ce qu'il peut faire pour vous.

Ma grand-mère fait les meilleurs petits pains, les plus moelleux et les plus moelleux que quiconque ait jamais goûtés. Le problème est qu'il y a une tonne d'ingrédients secrets (et je ne parle pas seulement d'amour) qui entrent dans ces petits pains, et ces ingrédients et ces instructions sont tous stockés dans la tête de ma grand-mère.

Nous avons tous des recettes de famille comme celle-là, et au lieu de les oublier, dans cet article, nous allons créer une application mobile pour iOS et Android en utilisant Xamarin.Forms qui les conservera pour moi et les générations futures de ma famille !

Dessin de petits pains avec montée de vapeur
Délicieux petits pains chauds ( Grand aperçu )

Donc, si vous êtes intéressé par l'écriture d'applications mobiles, mais que vous n'avez pas le temps d'écrire la même application encore et encore pour chaque plateforme, cet article est pour vous ! Ne vous inquiétez pas si vous ne connaissez pas le C# d'une salade de bretzels aux fraises ; J'écris des applications Xamarin depuis plus de 8 ans, et cet article est une visite guidée de Xamarin.Forms qui vise à vous donner suffisamment d'informations pour commencer à apprendre par vous-même.

Qu'est-ce que ce truc Xamarin?

Plus qu'un simple mot amusant à dire, Xamarin permet aux développeurs de créer des applications iOS et Android natives en utilisant exactement les mêmes SDK et contrôles d'interface utilisateur disponibles que dans Swift et XCode pour iOS ou Java et Android Studio pour Android.

Plus après saut! Continuez à lire ci-dessous ↓
Dessin de bonhomme allumette se demandant s'ils devraient développer pour iOS ou Android
Pour quelle plate-forme dois-je développer ? ( Grand aperçu )

La différence est que les applications sont développées avec C# en utilisant le .NET Framework et Visual Studio ou Visual Studio pour Mac. Les applications qui en résultent, cependant, sont exactement les mêmes. Ils ressemblent, se sentent et se comportent comme des applications natives écrites en Objective-C, Swift ou Java.

Xamarin brille en matière de partage de code. Un développeur peut créer et personnaliser son interface utilisateur pour chaque plate-forme à l'aide de contrôles natifs et de SDK, mais ensuite écrire une bibliothèque de logique d'application partagée qui est partagée entre les plates-formes.

Dessin de bonhomme allumette avec l'idée de développer pour les deux plates-formes à la fois en utilisant Xamarin
Ah ! Je vais choisir Xamarin ! ( Grand aperçu )

C'est ce partage de code qui permet de réaliser d'énormes gains de temps.

Et comme les délicieux petits pains que prépare ma grand-mère, une fois que j'ai eu le goût de partager du code - il est difficile de ne pas en vouloir plus - et c'est là que Xamarin.Forms entre en jeu.

Xamarin.FormsXamarin.Forms

Xamarin.Forms reprend le concept de développement Xamarin traditionnel et y ajoute une couche d'abstraction.

Au lieu de développer l'interface utilisateur pour iOS et Android séparément, Xamarin.Forms introduit une boîte à outils d'interface utilisateur qui vous permet d'écrire des applications mobiles natives à partir d'une base de code unique.

Pensez-y de cette façon : vous avez une application qui a besoin d'un bouton. Chaque plate-forme a le concept d'un bouton. Pourquoi devriez-vous avoir à écrire l'interface utilisateur plusieurs fois alors que vous savez que tout ce que l'utilisateur de votre application doit faire est d'appuyer sur un bouton ?

C'est l'un des problèmes que Xamarin.Forms résout.

Il fournit une boîte à outils des contrôles et des événements d'interaction utilisateur les plus couramment utilisés pour eux, de sorte que nous n'avons qu'à écrire les interfaces utilisateur pour nos applications une seule fois. Il convient de noter cependant que vous n'êtes pas limité aux contrôles fournis par Xamarin.Forms non plus - vous pouvez toujours utiliser les contrôles trouvés dans une seule plate-forme au sein d'une application Xamarin.Forms. De plus, nous pouvons partager la logique d'application entre les plates-formes comme auparavant.

Les statistiques de partage de code pour les applications développées avec Xamarin.Forms peuvent être hors du commun. Une application d'organisation de conférence a 93 % de son code partagé sur iOS et 91 % sur Android. L'application est open source. Jetez un œil au code.

Xamarin.Forms fournit plus que des contrôles d'interface utilisateur. Il contient également un framework MVVM, un service de messagerie pub/sub, une API d'animation et un service de dépendance, ainsi que d'autres.

Mais aujourd'hui, nous allons nous concentrer sur les capacités de l'interface utilisateur pour créer notre application de gestion de recettes.

L'application que nous allons créer

L'application du gestionnaire de recettes aura une interface utilisateur simple. Nous travaillerons dans la cuisine, il doit donc être facile à utiliser !

Il sera composé de 3 écrans . Le premier affichera une liste de toutes les recettes actuellement chargées dans l'application.

Capture d'écran de l'écran de la liste des recettes sur iOS
( Grand aperçu )

Ensuite, en appuyant sur l'une de ces recettes, vous pourrez voir ses détails sur un deuxième écran :

Capture d'écran de l'écran de détail de la recette sur iOS
L'écran de détail de la recette sur iOS ( Grand aperçu )

À partir de là, vous pouvez appuyer sur un bouton de modification pour apporter des modifications à la recette sur le troisième écran :

Capture d'écran de l'écran d'édition de recette sur iOS
L'écran d'édition de recette sur iOS ( Grand aperçu )

Vous pouvez également accéder à cet écran en appuyant sur le bouton Ajouter depuis l'écran de la liste des recettes.

L'environnement de développement

Les applications Xamarin sont construites avec C # et .NET, en utilisant Visual Studio sur Windows ou Visual Studio pour Mac sur Mac, mais vous devez également installer les SDK et les outils iOS ou Android. Obtenir tout installé, dans le bon ordre pourrait être un peu un problème, cependant, les installateurs de Visual Studio se chargeront de noter uniquement l'installation de l'IDE, mais aussi les outils de la plate-forme.

Bien qu'un Mac soit toujours requis pour créer des applications iOS, avec Xamarin, vous pouvez toujours développer et déboguer ces applications à partir de Visual Studio sur Windows ! Donc, si Windows est votre confiture, il n'est pas nécessaire de modifier complètement vos environnements.

Voyons maintenant comment Xamarin.Forms peut nous aider à enregistrer des recettes familiales à partir d'une seule base de code !

Page de la liste des recettes : présentation de l'interface utilisateur

Commençons par parler de la façon dont nous allons mettre en page l'interface utilisateur de notre application d'enregistrement de recettes !

Dans l'ensemble, chaque écran dans Xamarin.Forms est composé de 3 éléments. Une Page . Au moins un élément appelé Layout . Et au moins un Control .

La page

La page est la chose qui héberge tout ce qui est affiché à l'écran en même temps. La Page est également centrale dans la navigation au sein d'une application.

Dessin représentant une Page dans Xamarin.Forms
La page ( Grand aperçu )

Nous indiquons à Xamarin.Forms quelle Page afficher via un service de navigation . Ce service se chargera ensuite d'afficher n'importe quelle page d'une manière appropriée et native pour le système d'exploitation.

En d'autres termes, le code pour naviguer entre les écrans a également été abstrait !

Enfin, bien que ce ne soit pas la seule façon de le faire, je code l'interface utilisateur de mes Page en XAML. (L'autre façon serait d'utiliser C#.) XAML est un langage de balisage qui décrit l'apparence d'une page. Et pour l'instant, qu'il suffise de dire que c'est un peu similaire au HTML.

La disposition

Tous les contrôles d'une page sont organisés par ce qu'on appelle une mise en page.

Dessin représentant certaines mises en page dans Xamarin.Forms
Les mises en page ( Grand aperçu )

Une ou plusieurs mises en page peuvent être ajoutées à une page.

Dessin de la façon dont les mises en page interagissent avec la page
Dispositions sur la page ( Grand aperçu )

Il existe plusieurs types de mises en page dans les formulaires. Certaines des plus courantes incluent les mises en page Stack, Absolute, Relative, Grid, Scroll et Flex.

Dessin de plusieurs mises en page Xamarin.Forms et comment elles organisent leurs éléments enfants.
Dispositions communes Xamarin.Forms ( Grand aperçu )

Les contrôles

Enfin, il y a les contrôles. Ce sont les widgets de votre application avec lesquels l'utilisateur interagit.

Dessin de quelques contrôles Xamarin.Forms, chacun dessiné comme une boîte
Certains des contrôles ( Grand aperçu )

Les formulaires sont livrés avec de nombreux contrôles qui seront utilisés quel que soit le type d'application que vous créez. Des éléments tels que des étiquettes, des boutons, des zones de saisie, des images et, bien sûr, des vues de liste.

Lorsque vous ajoutez un contrôle à un écran, vous l'ajoutez à une mise en page. C'est la mise en page qui s'occupe de déterminer où exactement sur l'écran le contrôle doit apparaître.

Dessin d'une page contenant 2 mises en page, et ces mises en page organisant les champs selon le type de mise en page.
Tout s'emboîte ! ( Grand aperçu )

Donc pour générer les écrans suivants sur iOS et Android respectivement :

Capture d'écran de l'écran de la liste des recettes sur iOS et Android
Listes de recettes sur iOS (à gauche) et Android (à droite) ( Grand aperçu )

J'ai utilisé ce 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>

Il se passe quelques choses importantes ici.

Le premier est le <StackLayout> . Cela indique à Forms d'organiser tous les contrôles qui suivent dans une pile.

Il se trouve qu'il n'y a qu'un seul contrôle dans la mise en page, et c'est un <ListView> , et nous allons lui donner un nom afin que nous puissions le référencer plus tard.

Ensuite, il y a un peu de cérémonie passe-partout pour le ListView avant d'arriver à ce que nous recherchons : le <TextCell> . Cela indique à Forms d'afficher un texte simple dans chaque cellule de la liste.

Nous disons à <TextCell> le texte que nous voulons qu'il affiche grâce à une technique appelée Data Binding . La syntaxe ressemble à Text="{Binding Name}" . Où Name est une propriété d'une classe Recipe qui modélise… eh bien, Recipes.

Alors, comment les recettes sont-elles ajoutées à la liste ?

Avec chaque fichier XAML, il existe un fichier "code-behind". Ce code-behind nous permet de faire des choses comme gérer les événements d'interaction utilisateur, ou effectuer la configuration, ou faire d'autres logiques d'application.

Il existe une fonction qui peut être remplacée dans chaque Page appelée OnAppearing - qui, comme vous l'avez sûrement deviné, est appelée lorsque la Page apparaît.

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

Notez les recipesList.ItemsSource = AllRecipes;

Cela dit à ListView - "Hé ! Toutes vos données se trouvent dans l'énumérable App.AllRecipes (une variable à l'échelle de l'application) et vous pouvez utiliser n'importe laquelle des propriétés de son objet enfant pour effectuer une liaison !".

Une liste de recettes, c'est bien beau, mais vous ne pouvez rien cuisiner sans d'abord voir les détails de la recette, et nous allons nous en occuper ensuite.

Gestion des événements

Sans répondre aux touches de l'utilisateur, notre application n'est rien de plus qu'une liste de délicieuses recettes sonores. Ils sonnent bien, mais sans savoir les cuisiner, ça ne sert pas à grand chose !

Faisons en sorte que chaque cellule de la ListView réponde aux tapotements afin que nous puissions voir comment faire la recette !

Dans le fichier code-behind RecipeListPage , nous pouvons ajouter des gestionnaires d'événements aux contrôles pour écouter et réagir aux événements d'interaction de l'utilisateur.

Gérer les événements tactiles dans la vue de liste, puis :

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

Il s'y passe des trucs sympas.

Chaque fois que quelqu'un sélectionne une ligne, ItemSelected est déclenché sur le ListView .

Parmi les arguments transmis au gestionnaire, l'objet eventArgs a une propriété SelectedItem qui se trouve être tout ce qui est lié au ListView auparavant.

Dans notre cas, il s'agit de la classe Recipe . (Nous n'avons donc pas à rechercher l'objet dans la source principale - il nous est transmis.)

Page de détail de la recette

Bien sûr, il y a une page qui nous montre les ingrédients secrets et les instructions pour faire chaque recette, mais comment cette page s'affiche-t-elle ?

Dessin d'un bonhomme allumette habillé en chef qui est prêt à commencer à cuisiner.
Allons cuisiner ! ( Grand aperçu )

Remarquez l' await Navigation.PushAsync(detailPage); ligne d'en haut. L'objet Navigation est un objet indépendant de la plate-forme qui gère les transitions de page de manière native pour chaque plate-forme.

Jetons maintenant un coup d'œil à la page des détails de la recette :

Capture d'écran de l'écran de détail de la recette sur iOS et Android
Écrans de détail des recettes sur iOS (à gauche) et Android (à droite) ( Grand aperçu )

Cette page est également construite avec XAML. Cependant, la mise en Layout utilisée (FlexLayout) est assez cool car elle s'inspire de la 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>

Le FlexLayout organisera ses contrôles en lignes ou en colonnes. Le gros avantage vient cependant du fait qu'il peut détecter automatiquement la place qu'il reste sur l'écran pour placer un contrôle, et s'il n'y en a pas assez, il peut automatiquement créer une nouvelle ligne ou colonne pour l'adapter !

Cela aide grandement lorsqu'il s'agit de différentes tailles d'écran, qui sont nombreuses dans le développement mobile.

Eh bien, avec le FlexLayout qui nous aide à garder l'écran des détails en bon état, nous devons encore modifier ces recettes, n'est-ce pas ?

Vous avez probablement remarqué ceci :

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

Cette ligne est chargée de mettre un bouton dans la barre d'outils de l'application. Le Clicked="Edit_Clicked" indique au bouton que lorsqu'il est cliqué, recherchez dans le code derrière une fonction de ce nom, puis exécutez son code.

Ce qui, dans ce cas, consisterait à instancier la page d'édition de recette et à la pousser sur notre pile de navigation à l'aide de l'objet Navigation mentionné précédemment.

Page de modification de la recette

Une page avec une liste de recettes : check ! Une page avec tous les détails pour réaliser les recettes : check ! Il ne reste plus qu'à créer la page que nous utilisons pour entrer ou modifier une recette pendant que nous regardons grand-mère faire sa magie !

Tout d'abord, regardez les écrans :

Capture d'écran de l'écran d'édition de recette sur iOS et Android
Écrans d'édition de recettes sur iOS (à gauche) et Android (à droite) ( Grand aperçu )

Et maintenant le code :

 <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>

Il y a un peu plus de code ici, et c'est parce que j'utilise la disposition de la Grid pour spécifier comment tout doit être disposé dans un modèle bidimensionnel.

Et notez également aucune liaison de données ici. Parce que je voulais donner un exemple de la façon dont on remplirait les contrôles uniquement à partir du code derrière le fichier :

 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(); }; }

Vous voyez cette propriété TheRecipe ? C'est au niveau de la page, contient toutes les données d'une recette particulière et est défini dans le constructeur de la page.

Deuxièmement, les gestionnaires d'événements Clicked pour saveButton et cancelButton sont totalement .NET-ifiés (et oui, j'invente souvent mes propres mots.)

Je dis qu'ils sont .NET-ified car la syntaxe pour gérer cet événement n'est pas native de Java ni d'Objective-C. Lorsque l'application s'exécute sur Android ou iOS, le comportement sera exactement comme un clic Android ou un iOS TouchUpInside.

Et comme vous pouvez le constater, chacun de ces gestionnaires d'événements de clic appelle des fonctions appropriées qui enregistrent la recette et suppriment la page, ou suppriment uniquement la page.

Voilà, nous avons l'interface utilisateur désactivée pour enregistrer les recettes d'ici la fin des temps !

CSS Quoi?!? Ou rendre l'application jolie

Garder le meilleur pour la fin : Xamarin.Forms 3.0 nous donne, entre autres, la possibilité de styliser les contrôles à l'aide de CSS !

Le CSS Xamarin.Forms n'est pas à 100% ce à quoi vous pourriez être habitué du développement Web. Mais c'est assez proche pour que toute personne familiarisée avec CSS se sente comme chez elle. Comme moi chez grand-mère !

Prenons donc la page Détails de la recette et refactorisons-la, afin qu'elle utilise des feuilles de style en cascade pour définir les éléments visuels au lieu de tout définir directement en ligne dans le XAML.

La première étape consiste à créer le document CSS ! Dans ce cas, il ressemblera à ce qui suit :

 .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; }

Pour la plupart, cela ressemble à du CSS. Il y a des cours là-bas. Il existe un seul sélecteur pour un type de classe, Image . Et puis une bande de proprietaires.

Certains de ces setters de propriétés, tels que flex-wrap ou flex-basis sont spécifiques à Xamarin.Forms. À l'avenir, l'équipe préfixera ceux avec xf- pour suivre les pratiques standard.

La prochaine étape consistera à l'appliquer aux contrôles 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>

Voici à quoi ça ressemblait avant.

Dans Xamarin.Forms, pour référencer le document CSS, ajoutez un <StyleSheet Source="YOUR DOC PATH" /> . Ensuite, vous pouvez référencer les classes dans chaque contrôle via la propriété StyleClass .

Cela nettoie définitivement le XAML et rend également l'intention du contrôle plus claire. Par exemple, il est maintenant assez évident de savoir ce que font ces <BoxView StyleClass="spacer" /> !

Et l' Image est stylisée parce que c'est une Image et la façon dont nous avons défini le sélecteur dans le CSS.

Certes, CSS dans Xamarin.Forms n'est pas aussi complètement implémenté que son cousin Web, mais c'est quand même plutôt cool. Vous avez des sélecteurs, des classes, vous pouvez définir des propriétés et, bien sûr, tout ce qui se passe en cascade !

Sommaire

Trois écrans, deux plates-formes, un article et des recettes infinies sauvegardées ! Et vous savez ce qu'il y a d'autre? Vous pouvez créer des applications avec Xamarin.Forms pour plus qu'Android et iOS. Vous pouvez créer des plates-formes UWP, macOS et même Samsung Tizen !

Dessin de petits pains avec montée de vapeur
Délicieuse! ( Grand aperçu )

Xamarin.Forms est une boîte à outils d'interface utilisateur qui vous permet de créer des applications en écrivant l'interface utilisateur une seule fois et en affichant l'interface utilisateur de manière native sur les principales plates-formes.

Pour ce faire, il fournit un SDK qui est une abstraction des contrôles les plus couramment utilisés sur les plates-formes. En plus de la qualité de l'interface utilisateur, Xamarin.Forms fournit également un framework MVVM complet, un service de messagerie pub/sub, une API d'animation et un service de dépendance.

Xamarin.Forms vous offre également les mêmes avantages de code que le développement Xamarin traditionnel. Toute logique d'application est partagée sur toutes les plates-formes. Et vous pouvez développer toutes vos applications avec un seul IDE en utilisant un seul langage - c'est plutôt cool !

Quelle est la prochaine étape ? Téléchargez le code source de cette application Xamarin.Forms pour lui donner un tour vous-même. Ensuite, pour en savoir plus sur Xamarin.Forms, y compris la possibilité de créer une application dans votre navigateur, consultez ce didacticiel en ligne !