Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Xamarin.Forms Partie 1 Cross-Plateforme et Cross UI

[new:31/08/2014]Dans mon billet du 2 juin dernier, “Xamarin 3.0 entre évolution et révolution” je vous parlais des Xamarin.Forms, une approche totalement cross-plateforme de l’UI. Il est temps de les voir à l’œuvre !

UI Cross-plateforme

imageDans l’article cité en introduction je vous ai présenté les Xamarin.Forms, cette nouvelle librairie qui est fournie avec Xamarin 3.0 et qui permet d’écrire des UI totalement portables sous toutes les plateformes mobiles mais pas seulement puisque le code peut tourner sur Mac et bien sûr sur PC…

C’est un pas décisif en avant ! Jusqu’à lors Xamarin apportait la compatibilité du code C# et de la plateforme .NET sous Android et iOS, c’était déjà énorme. Aujourd’hui c’est l’UI qui devient portable avec un même code, de Windows Phone à Android en passant par iOS. Xamarin 3.0 c’est aussi la possibilité de coder en F# en plus de C# (mais pas tous les types de projets, mais Visual Studio se charge déjà d’une partie). On se rappellera d’ailleurs ma récente série de 6 billets sur la programmation fonctionnelle et F#(voir la liste des billets sur F#)

Bien entendu il existe déjà des solutions pour développer en cross-plateforme  notamment en C# / Visual Studio. Je vous ai montré celle utilisant Xamarin et MvvmCross (liste des billets sur le cross-plateforme). Je ne parle pas des plateformes hybrides fonctionnant sous Html et JS qui hélas n’ont pas prouvé leur efficacité face au code natif. Mais tout le monde aujourd’hui, même des éditeurs de composants comme Telerik, proposent “leur” solution cross-plateforme qui lave plus blanc et qui sent meilleur. Une telle débauche d’effets pas toujours spéciaux s’explique par le besoin réel et de plus en plus pressant de trouver une solution au problème de la fin de l’hégémonie du PC. Satya Nadella a raison quand il parle d’ère post-PC, et il n’est pas le premier à l’évoquer d’ailleurs.

Aujourd’hui la pression monte autour des entreprises, cette pression vient de l’extérieur, du grand public qui a adopté en masse tablettes et smartphones en délaissant Windows et les PC. La pression est aussi interne : les commerciaux voudraient avoir leur catalogue de produits sur tablettes, les superviseurs aimeraient contrôler les cadences depuis leur smartphone, les clients même réclament des apps natives à la place des sites Web habituels… Toute cette pression qui urge de toute part les DSI d’agir, et toute cette angoisse de se fourvoyer qui les fait différer sans cesse les décisions… A un moment ou un autre il va falloir évacuer cette pression pour que tout n’explose pas… Passer enfin à l’action et rattraper le retard. Ne pas se tromper est gage d’une bonne gestion, mais c’est à l’extrême une apologie de l’immobilisme… Rester en C#, conserver Visual Studio, le framework .NET, tout cela évite déjà les remises en cause, et si en plus on ajoute la portabilité des UI, alors quelles raisons pourraient encore empêcher les DSI de lâcher la pression ? …

Car si Xamarin nous permettait déjà de rester en natif tout en utilisant notre langage préféré, C#, une plateforme rodée et puissante, .NET et un EDI au-dessus du lot, Visual Studio, il restait tout de même un point gênant, même avec MvvmCross : il fallait recréer les UI pour chaque plateforme.

Certes le gain était déjà énorme, travailler en MVVM avec un code unique pour toutes les plateformes mobiles c’est ce dont nous avons besoin pour relever le défi d’un marché désormais éclaté en plusieurs OS et ce pour toujours certainement. Mais pour géant qu’était le pas le développeur se trainait toujours avec un boulet à la patte… l’UI.

Xamarin.Forms nous affranchit de ce boulet en rendant les UI tout aussi portables que le code.

Pour l’instant le procédé est jeune, les composants utilisables restent peu nombreux et il n’existe pas de designer visuel, tout se fait par code C# ou XAML. Mais parions que tout cela va évoluer très vite surtout que déjà l’essentiel est là, productif et regroupant le nécessaire pour coder cross-plateforme des UI parfaitement utilisables.

Rappelons aussi que Xamarin.Forms n’est pas un procédé exclusif de type tout ou rien, dans une même application on peut mixer sans aucun problème des fiches créées avec Xamarin.Forms et d’autres entièrement écrites en natif. Cet aspect est essentiel car les Xamarin.Forms, à défaut de permettre pour l’instant de débrider la créativité visuelle des designers n’en reste pas moins un excellent moyen d’accélérer le développement. Par exemple on peut supposer que la page des paramètres, celle du login d’une app peuvent se satisfaire d’une mise en page propre et fonctionnelle sans pour autant nécessiter tout un processus de design couteux et sophistiqué. C’est du temps donc de l’argent gagné. Tout de suite, mais aussi pour l’avenir puisque ces forms seront maintenables sous la forme d’un code unique cross-plateforme pour toute la vie de l’app… (on peut évidemment aussi décider de les changer pour du natif plus tard si on veut !).

Tout en Xamarin.Forms, partiellement en Xamarin.Forms, pour tout de suite, pour plus tard, définitivement, temporairement… Toutes les options sont possibles et vous permettrons de produire, enfin, des applications cross-plateformes dans un budget maitrisé car vous pouvez le faire avec vos connaissances actuelles, vos compétences. Le delta à apprendre existe, il ne faut pas le minimiser, mais c’est jute un delta, pas une formation à partir de zéro.

D’ailleurs cette petite série de billets sur les Xamarin.Forms finira j’en suis certain de vous convaincre…

La notion de Form

rolodexCette notion de Form (ou Formulaire en français) est l’une des plus classiques, un des paradigmes de base du codage des UI même depuis les temps anciens. La classe mère des fiches en Delphi s’appelait déjà il y a longtemps TForm – c’était en 1995 à la sortie de Delphi 1.0 ! Plus de 20 ans que ce concept de “fiche” rode dans les langages et dirige nos écrans… De l’écran vert cathodique à l’AMOLED des smartphones haut-de-gamme, tous nécessitent depuis la nuit des temps informatique, celle des Micral, Questar et autre IBM 5250, de pouvoir afficher et saisir des données sous la forme de fiche, skeuomorphisme hérité du temps du papier et des fiches rangées dans leur Rolodex ! . Les données sont le sang qui coule dans les veines de tous les ordinateurs sans qui leur existence même n’aurait plus de sens. Encore faut-il les afficher et en autoriser la saisie ou la modification !

Les Xamarin.Forms ne font que nous apporter ce concept de fiche, mais elles le font en étant cross-plateforme. C’est là que réside la nouveauté et l’intérêt.

Chaque page de l’application est ainsi représentée par une fiche, un formulaire, une Form, et l’utilisateur navigue de Form en Form. Certaines Form sont simples (login par exemple) d’autres sont plus complexes (onglets, navigation vers des pages de détail…).

Je sais, des UI cross-plateformes cela existait déjà en 2007 avec la première version de Silverlight, et avec éditeur visuel le tout en vectoriel… Mais le futur avance par saccades et même parfois en reculant… pour mieux sauter ? Peut-être avec les Xamarin.Forms !

Un paradigme deux écritures

Annonçant peut-être le Saint Graal de la portabilité totalement pilotée en mode visuel, les Xamarin.Forms peuvent en effet se définir de deux façons très différentes pour un résultat visuel identique :

  • Par code C#, en structurant les conteneurs, les contenus, comme on sait le faire par code en XAML ou même avec ces bonnes vieilles Windows Forms;
  • En code XAML : Xamarin.Forms n’est hélas pas un portage de XAML, je vendrais mon âme au premier diable qui passe pour qu’il en soit ainsi, non mais elles supportent astucieusement un mode de définition XML avec un sous-ensemble des possibilités de XAML ce qui ouvre la voie à un prochain éditeur visuel peut-être… Une sorte de retour de Silverlight et la boucle sera bouclée…

 

Nous verrons dans cette série comment utiliser ces deux modes de création de fiches même si nous allons commencer par la voie la plus simple, la plus directe : créer une fiche en mode C# avec Xamarin.Studio. La même chose peut être faite avec Visual Studio et c’est lui que nous utiliserons plus tard d’ailleurs. Mais il est intéressant de rappeler l’existence de Xamarin.Studio qui évolue sans cesse et surtout qui est lui-même portable sur PC, Mac et Linux…

Un premier exemple

Avant de nous lancer dans l’étude plus approfondie des Xamarin.Forms je pense que réaliser un premier exemple très simple permettra de mieux fixer l’ensemble du processus, comment tout s’enchaine naturellement.

Comme je le disais plus haut je vais utiliser ici Xamarin.Studio qui a l’avantage d’être un environnement portable toujours identique sur toutes les plateformes. Vous pouvez donc écrire des applications Mac et iOS avec cet outil sans jamais voir un PC si cela vous chante. Plus tard nous utiliserons Visual Studio qui reste le meilleur EDI du marché pour PC.

Créer un projet

Fichier / Nouveau Projet, c’est un grand classique qui ne dépaysera personne… Suit une boîte de dialogue à la Visual Studio pour sélectionner le langage et le type de projet.

Ici je vais opter pour une “Blank App (Xamarin.Forms Shared)” c’est à dire une application vide, cross-plateforme, utilisant la méthode du code partagé. L’autre choix utilise les PCL que nous avons vu très souvent dans mes vidéos sur le cross-plateforme. On peut choisir l’un ou l’autre de ces deux modes, le résultat sera le même mais la façon d’y arriver diffèrera un peu, code partagé et PCL offrant chacun des possibilités légèrement différentes.

Il existe un troisième type de projet, classique lui-aussi, celui permettant de créer une bibliothèque de code (une DLL).

image

Par défaut je vais obtenir une solution contenant un projet pour le code partagé et un autre pour Android. Pourquoi un projet Android ? D’abord parce sous Xamarin.Studio Android dispose d’un système complet, Xamarin ne s’est pas amusé à refaire les éditeurs Windows Phone qui se trouvent dans Visual Studio. Donc tout naturellement c’est plutôt un projet que l’EDI est capable de gérer qui est créé par défaut.

Vient ensuite la question piège : puisque tout est portable, le code depuis longtemps et maintenant les fiches avec Xamarin.Forms, alors pourquoi donc commencer avec un projet spécialisé pour Android ? La réponse est tout aussi simple : parce que d’une part on pourra ajouter ensuite tous les projets qu’on veut, la solution de départ n’en contient qu’un seul c’est un exemple et que, d’autre part, si presque tout peut être partagé il reste parfois des personnalisations à effectuer selon la plateforme. Avoir un projet pour chacune permet ainsi de s’assurer de pouvoir faire ces petites personnalisations si nécessaire sans tout casser… Une autre raison s’impose aussi : chaque cible nécessite son propre compilateur, ses propres préférences et autorisations etc. Il faudra attendre très longtemps je pense pour que Apple, Google et Microsoft se mettent d’accord sur un langage et une plateforme interopérable ! De fait c’est Xamarin qui permet de centraliser toutes les versions et de les compiler.

Alors pourquoi un projet Android ? J’ai déjà expliqué que l’EDI Xamarin Studio ne sachant pas gérer avec la même aisance les projets Windows Phone il est normal que le projet par défaut soit en Android qui est totalement couvert par l’EDI. Oui mais pourquoi pas de projet iOS alors ? Cette fois-ci ce n’est pas de la faute de Microsoft mais de Apple qui ne s’est jamais ouvert au monde PC. De fait compiler des projets iOS réclame d’avoir un Mac. Idem pour le débogue. On voit bien que dès lors le fameux pince-mi pince-moi à trois partenaires n’en laisse qu’un seul de véritablement portable et universel : Android.

Bref après avoir répondu à votre saine et naturelle curiosité revenons à notre Solution… (c’est vrai, après on dira que c’est moi qui aime faire des digressions, que nenni, je ne fais que répondre par avance aux questions légitimes du lecteur ! Sourire)

image

Le premier projet est celui du code partagé, il ne contient que “app.cs” qui est le code de la classe App, celle qui démarre et représente l’application. Par défaut elle contient une méthode GetMainPage qui retourne un objet ContentPage construit par code. Le projet Android, dans son activité principale (notion propre à Android) initialise son affichage en appelant la méthode GetMainPage. Si nous compilons en l’état nous aurons ainsi une application Android affichant glorieusement une seule page avec le texte “Hello, Forms!”. Le principe global reste le même pour toutes les plateformes : le code de l’UI comme du reste est centralisé dans une PCL ou un projet partagé le tout étant utilisé par tous  les projets spécifiques. La nuance avec ce que nous avons pu voir dans mon cycle de vidéos sur le cross-plateforme c’est qu’ici les projets spécifiques peuvent fort bien n’être que des coquilles dans lesquelles on n’intervient jamais, tout était en mode cross-plateforme le code et l’UI alors qu’en utilisant MvvmCross on code les UI en natif, seul le code est partagé.

Les deux approches ont leurs avantages. Celle que nous propose Xamarin est très directe et permet de produire vite un code unique cross-plateforme.

Et c’est énorme !

Nous allons le vérifier tout de suite en faisant évoluer un tout petit peu cette solution de base vide.

Ecrire un modèle de données

A la base de tout logiciel comme je le disais on trouve des données. Il nous en faut pour avancer. Dans l’application partagée créons un sous-répertoire “Model” et plaçons-y une nouvelle classe décrivant (sommairement) un oiseau : Nom vernaculaire, nom latin, poids moyen et description.

Nous obtenons très rapidement un code de ce type :

image

 

Pour cet exemple nous ferons bien entendu abstraction de toute la logique habituelle du INPC et des tests de validité des données.

Ecrire le ViewModel

Il n’est pas question de sacrifier aux bonnes habitudes. Nous simplifions les tests mais pas l’essentiel ! Nous allons ainsi ajouter un répertoire “ViewModel” au projet partagé et y placer le code du ViewModel de notre page principale.

Interlude : <musique d’ascenseur> … <ding dong ding> … <voix d’aéroport>En raison d’un incident technique les passagers à destination de Xamarin.Studio sont priés de se rendre porte Visual Studio Hall Microsoft<ding dong ding>

Je n’ai pas trop le temps de chercher à comprendre mais sous Xamarin Studio la compilation indique un problème d’espace de nom dans mon projet partagé… Et quand j’ouvre la même solution sous VS 2013 tout passe bien alors même que c’est le compilateur Xamarin qui est appelé aussi… Donc je switche sauvagement sous VS pour la fin de l’article, comme ça vous aurez vu un peu des deux dans le même projet ce qui prouve même la compatibilité totale entre les deux EDI (soyons positifs) !

 

Donc revenons à notre ViewModel. C’est un code rudimentaire mais fonctionnel :

namespace DotBlogTest.ViewModel
{
	public class BirdsViewModel
	{
		public ObservableCollection<Bird> Birds { get; private set; }

		public BirdsViewModel ()
		{
			Birds = new ObservableCollection<Bird> ();
			Birds.Add (new Bird {
				Name = "Rouge gorge",
				LatinName = "Erithacus rubecula",
				AverageWeight = 20,
				Description = "Petit passereau familier des jardins"
			});
			Birds.Add (new Bird {
				Name = "Mésange huppée",
				LatinName = "Lophophanes cristatus",
				AverageWeight = 11,
				Description = "Petit passereau  de la famille des Paridés"
			});
			Birds.Add (new Bird {
				Name = "Pic vert",
				LatinName = "Picus viridis",
				AverageWeight = 200,
				Description = "Présent presque partout en Europe fait son nid en creusant un arbre"
			});
			Birds.Add (new Bird {
				Name = "Chardonneret élégant",
				LatinName = "Carduelis carduelis",
				AverageWeight = 15,
				Description = "Oiseau partiellement migrateur à la robe bariolée et exclusivement granivore"
			});

		}
	}
}

 

Le ViewModel est une classe “normale”. Ici pas de chichi, pas de framework MVVM super sophistiqué, on fait tout à la main, et ça marche quand même ! Le lecteur fidèle n’est pas étonné puisque dans le passé je vous ai déjà expliqué comment appliquer MVVM sans aucun framework (le 9 janvier 2010 dans l’article M-V-VM avec Silverlight ce qu’on retrouve revisité dans le livre ALL.DOT.BLOG  “Méthodes & Frameworks MVVM”).

Ce code est ultra simple et le ViewModel ne contient qu’une seule propriété de type collection d’oiseaux (classe Bird), 95% du code restant est consacré à l’initialisation de cette collection avec quelques items de démonstration.

La page principale

Nous avons une classe Bird, le Model, nous avons une classe BirdViewModel, … le ViewModel (il y en a deux qui suivent ça fait plaisir !) qui initialise une liste d’oiseaux pour la démonstration. C’est déjà pas mal mais c’est du C# pour débutant. Il nous faut afficher cette liste d’oiseaux sur tous les mobiles de la planète et pour cela nous avons besoin d’une fiche. Donc d’une page de contenu de Xamarin.Forms.

Cette page s’appelle BirdsPage sans grande originalité :

public class BirdsPage : ContentPage 
{
  public BirdsPage ()
 {
   Title = "Oiseaux";
   var list = new ListView();
   Content = list; ...
  }
}
 

 

Pour l’instant ne dévoilons pas toute la mécanique pour regarder l’allure générale. Tout d’abord la classe créée descend de ContentPage fournie par Xamarin.Forms. C’est l’un des styles disponible, le plus simple avec un objet conteneur qui remplit tout l’espace. Nous aurions pu choisir une MasterDetailPage, une NavigationPage, une TabbedPage ou une CarouselPage par exemple, le choix est vaste et permet de cerner la majorité des mises en page d’une application.

image

Ici pour faire simple c’est donc ContentPage qui a été choisie. Le code ne contient que le constructeur de la page car tout y est : l’initialisation du titre de la page et celle de sa propriété Content, le contenu unique de la page. Ici ce contenu (qui peut être n’importe quoi un peu comme un Border XAML) est une liste et plus précisément une ListView fournie elle aussi par Xamarin.Forms. Cette classe, comme d’autres dans les Xamarin.Forms apporte quelque chose d’énorme : le data binding qui devient, de fait, cross-plateforme lui aussi.

Comme on peut se l’imaginer le but de cette classe est de fournir un support visuel de type liste, ce qui tombe bien puisque nous voulons afficher la liste des oiseaux.

Toutefois on s’aperçoit vite que mon code est un peu trop court pour être honnête… En effet créer une ListView c’est bien mais encore faut-il lui expliquer quoi afficher… C’est simple, nous allons créer une instance du ViewModel et passer à l’ItemsSource de la ListView la propriété Birds de ce dernier (la collection). Du MVVM assez classique bien que tout “en mode manuel”.

Si nous lançons l’app tout de suite et comme s’y attendent les plus attentifs nous aurons bien une liste mais d’éléments répétant inlassablement le nom de la classe de l’objet oiseau (Bird) qui sera passé… Il manque à notre ListView un ItemTemplate ou un équivalent pour savoir comment afficher chaque élément de la liste.

Nous allons ainsi créer maintenant une instance de la classe DataTemplate pour le type “TextCell”, une “cellule” qui ne contient que du texte sur deux lignes, une avec une police assez grosse, le texte, et une seconde ligne plus petite, le détail, mise en page assez classique dans les listes. C’est déjà tout fabriqué il suffit donc d’initialiser les deux champs (Text et Detail) en utilisant les noms des propriétés de Bird (Name et Description).

Enfin nous indiquons à liste que son ItemTemplate est le DataTemplate qui vient d’être créé… C’est facile, c’est, aux noms de classes qui peuvent légèrement différer, le même code que ce que nous écririons en C# pour créer “à la main” une petite page XAML avec un conteneur, une liste et un data template.

Le code complet devient donc :

using DotBlogTest.Model;
using DotBlogTest.ViewModel;
using Xamarin.Forms;

namespace DotBlogTest.Form
{
	public class BirdsPage : ContentPage 
	{
		public BirdsPage ()
		{
			Title = "Oiseaux";
			var list = new ListView {ItemsSource = new BirdsViewModel().Birds};
			var cell = new DataTemplate (typeof(TextCell));
			cell.SetBinding (TextCell.TextProperty, "Name");
			cell.SetBinding (TextCell.DetailProperty, "Description");
			list.ItemTemplate = cell;
			Content = list;
		}
	}
}

 

C’est effectivement très simple. Pour l’instant notre liste n’est pas interactive mais elle fonctionne. Reste pour lancer un test à modifier la méthode GetMainPage de “app.cs” du projet partagé en supprimant le code de démonstration Xamarin et en demandant la création de notre page liste des oiseaux, BirdsPage. Comme nous souhaitons améliorer ensuite l’app pour ajouter l’affichage du détail nous aurons besoin du système de navigation, la page sera retournée dans une “enveloppe navigationnelle”. Mais c’est tellement plus simple quand on regarde le code :

using System;
using DotBlogTest.Form;
using Xamarin.Forms;


namespace DotBlogTest
{
	public class App
	{
		public static Page GetMainPage ()
		{	
			var birds = new BirdsPage();
			return new NavigationPage (birds);
		}
	}
}

 

J’avais dit que c’était simple, je ne mentais pas. On créée une instance de BirdsPage et on la retourne enveloppée dans un objet NavigationPage. La navigation peut être sophistiquée, ici nous n’écrirons rien d’autre que cela et utiliserons les mécanismes par défaut. Quand nous aurons ajouté la page détail il suffira à l’utilisateur d’utiliser la touche retour arrière de son appareil pour revenir à la liste. C’est aussi simple que cela.

Voici à quoi cela ressemble maintenant :

image

 

C’est déjà assez sympa puisque ça marche… et que ce code il faut le redire est uniquement du code générique qui tournera tel quel sur toutes les cibles ! D’ailleurs à aucun moment nous n’avons touché au projet Android qui sert de support à l’article et nous n’y toucherons jamais, vraiment jamais…. Tout se passe uniquement dans le projet partagé qui, comme je le présentais en début d’article pourrait aussi être un projet PCL. C’est au choix. En fin d’article je vous donne le code source de la solution, à vous d’ajouter le support Windows Phone 8.1 pour vous entrainer (c’est facile il n’y a presque rien à faire) !

Maitre / Détail

Soyons fou ! Imaginons maintenant qu’on veuille que l’utilisateur puisse choisir un oiseau de la liste et que cette action affiche une seconde page avec le détail de la fiche du volatile. C’est moi qui tape le code, alors n’hésitez pas, c’est la maison qui offre ! Ce qui me rappelle un grand principe dans notre métier applicable aussi dans la vie de tous les jours : Rien n’est impossible pour celui qui n’a pas à le faire lui-même.

Pour ajouter ce comportement maitre / détail nous aurons besoin d’une seconde page mais aussi d’ajouter quelque chose pour déclencher la navigation au moment du touch sur l’élément de la liste.

Page détail

La page détail ne sera pas différente de la page principale, nous allons choisir ici aussi une ContentPage. Et comme nous le ferions pour du XAML écrit en C# nous allons construire l’imbrication des éléments. Pour rester dans la sobriété nous utiliserons un StackPanel, enfin son équivalent Xamarin.Forms, puis nous empilerons à l’intérieur d’autres StackPanel en mode horizontal contenant un titre et un contenu. C’est vraiment de la mise en page de base, mais ça fonctionne là encore. Beaucoup de logiciels ne réclament pas plus que ça pour être utiles et adorés des utilisateurs !

Ce qui nous donne le code suivant :

using System;
using System.Collections.Generic;
using System.Text;
using DotBlogTest.Model;
using Xamarin.Forms;

namespace DotBlogTest.Form
{
    public class DetailPage : ContentPage
    {
        public DetailPage(Bird bird)
        {
            Title = bird.Name;
            var stack = new StackLayout {Orientation = StackOrientation.Vertical};
            stack.Children.Add(AddRow("Nom: ",bird.Name));
            stack.Children.Add(AddRow("Nom Latin: ",bird.LatinName));
            stack.Children.Add(AddRow("Poids moyen: ",bird.AverageWeight.ToString()));
            stack.Children.Add(new Label{Text = bird.Description});
            //var details = new Label {Text = bird.Name + " " + bird.LatinName};
            Content = new ScrollView {Padding = 20, Content = stack};
        }

        private Layout<View> AddRow(string label, string content)
        {
            var s = new StackLayout {Orientation = StackOrientation.Horizontal};
            s.Children.Add(new Label{Text = label,TextColor = Color.Gray});
            s.Children.Add(new Label{Text = content, TextColor = Color.White});
            return s;
        }
    }
}

 

La classe DetailPage descend ainsi de ContentPage comme la page principale et seul son constructeur est utilisé pour l’initialiser. Mais cette fois-ci nous utiliserons un constructeur à un paramètre : l’instance de l’oiseau à afficher.

Le reste est juste verbeux et répétitif : on initialise le titre de la page en utilisant le nom de l’oiseau, on créée un StackLayout équivalent du StackPanel, et on lui ajoute des enfants en utilisant une méthode “AddRow” qui retourne un StackLayout horizontal avec un titre et un texte. La dernière ligne ajoutée au StackLayout est la description de la classe Bird qui prendra ainsi tout le reste de la page.

Ici nous ne prévoyons pas que le contenu dépasse la hauteur de l’écran, c’est un peu un tort car dans la réalité on ne sait pas de quelle résolution disposera l’utilisateur. Dans la page principale tout est géré par la ListView mais ici il faudrait ajouter un conteneur général de type ScrollView pour bien faire. Cela tombe bien car Xamarin.Forms possède une classe de ce nom… je vous laisse l’ajouter pour vous entraîner…

Une fois le type de page choisi, Xamarin.Forms met à notre disposition des conteneurs de mise en page différents (ci-dessous). Le StackLayout ou le ScrollView en sont une illustration. Si la page elle-même ne peut être que de l’un des types proposés, la mise en page peut être beaucoup plus complexe et les conteneurs imbriqués les uns dans les autres, comme en XAML.

image

Notre page secondaire est maintenant opérationnelle ne reste plus qu’à déclencher son affichage…

Détecter le touch et naviguer

Pour naviguer depuis la page principale il faut intervenir sur la ListView et capturer le touch. Ensuite il faut récupérer l’item courant, une instance de Bird, et demander enfin la navigation sur une nouvelle instance de la page secondaire en lui passant en paramètre l’oiseau sélectionné. Facile :

En fin de code de la création de la page principale nous ajoutons :

list.ItemTapped += (sender, args) =>
		                       {
		                           var bird = args.Item as Bird;
		                           if (bird == null) return;
		                           Navigation.PushAsync(new DetailPage(bird));
		                           list.SelectedItem = null;
		                       };

L’évènement ItemTapped correspond au touch ou au clic. On le définit en utilisant une expression Lambda (ceux qui ont suivi la série sur F# ces derniers jours savent mieux de quoi je veux parler !). L’expression transtype l’item retourné dans les arguments de l’évènement, si la valeur est nulle il ne se passe rien, si elle est non nulle on appelle le PushAsync de l’objet Navigation avec une nouvelle instance de la page détail dont le paramètre de création est l’item. Comme on peut l’imaginer cette action “empile” la page dans le système de navigation. Pour le confort de l’utilisateur et étant donné l’ergonomie ultra simplifiée de notre app nous annulons la sélection qu’il vient de faire en passant l’item sélectionné de la liste à null.

Let’s go !

Même si c’est difficile à croire ou à réaliser, l’application est terminée et elle fonctionne… Une application totalement portable dans tous les environnements sans en changer une seule ligne de code …

Pour cet article je n’ai implémenté que l’application Android, comme je fourni le code source du projet, amusez-vous à ajouter l’application Windows Phones, Mac, iOS … Lâchez-vous c’est fait pour ça !

Le GIF ci-dessous vous montre l’application en cours d’utilisation avec la sélection d’un oiseau dans la liste et l’affichage de son détail.

 

bird

 

Conclusion

Simple, fonctionnel, portable.

Que demande le peuple ? Rien de plus.

Que demande vos commerciaux, votre patron, vos utilisateurs ? Rien de plus.

Combien de temps pour une application totalement portable cross-plateforme avec gestion de la navigation et du maître / détail ? Quelques minutes et plusieurs heures pour l’article ! Et pour une poignée de minutes en plus on aurait pu ajouter la sauvegarde des données et la saisie par l’utilisateur. Mais nous verrons ça autrement dans d’autres articles sur les Xamarin.Forms…

Tout le monde n’est pas éditeur de jeu ou d’applications qui remplacent un site web institutionnel. Il y a aussi la foule d’entreprises, petites ou plus grandes, qui ont besoin rapidement d’intégrer les mobiles dans leur environnement. Toute le monde n’a pas vocation à placer des apps sur les Stores, au contraire, la majorité des applications d’entreprise sont réservées à un usage interne.

Avec les Xamarin.Forms la panoplie est complète pour créer rapidement des applications professionnelles pour toutes les plateformes.

Avec quelques efforts en plus on peut les designer pour leur donner un “look” et en faire des applications destinées aux clients par exemple. Et avec un peu plus de travail on peut en faire des apps commerciales placées sur les Stores…

Aujourd’hui c’est là, sur la table, c’est possible, pas très cher.

A vous de voir s’il est nécessaire d’inventer de nouvelles excuses pour ne pas vous lancer…

Et pour en voir plus : Stay Tuned !

PS : comme promis le code de la solution (VS 2013 avec tous les patchs et bien entendu Xamarin 3.x) :

blog comments powered by Disqus