Skip to content

andrestalavera/ExpertsBlog

Repository files navigation

Applications mobiles avec Xamarin.Forms

Les approches du développement mobile :

  • Applications développées avec les langages/technologies Java ou Kotlin pour Android ou Objective-C ou Swift pour iOS/iPadOS.
  • Applications développées avec des frameworks Xamarin, Flutter, etc. qui traduisent le code source (C#, Dart, ...) dans un code natif à travers des brides (ponts).
  • Applications développées avec une technologies front (HTML, React, ...), parfois accompagnées de wrappers (PhoneGap, ...).

Les approches technologiques :

Technologie Code métier Code UI Android iOS / iPadOS
Android Java/Kotlin AXML
iOS/iPadOS Objective-C/Swift XIB (Xcode Interface Builder, page par page) / Storyboard (toutes les pages).
React Native React (Typescript) HTML, React, ...
PWA JavaScript, Typescript, ReactJS, Angular, Blazor (C#), ... HTML, technologie front (ReactJS, Angular, Blaozor, Razor, ...), ...
Flutter Dart Dart
Xamarin.Android C# AXML (natif Android)
Xamarin.iOS C# XIB, Storyboards (natif iOS)
Xamarin.Forms C# XAML (partagé)

Xamarin.Forms deviendra MAUI en novembre 2022.

Xamarin.X se base sur Mono (et pas .NET Framework/.NET Core/.NET). C'est une implémentation de .NET (grâce au standard ECMA-335) sur les distributations Linux (Ubuntu, Xubuntu, DebianOS, OpenSuse, ...).

Prérequis pour développer avec Xamarin

Technologie Installations Windows Installations macOS
Xamarin.Android SDK Android (pour les versions), JDK, Visual Studio avec les outils Xamarin, NDK, Emulateurs. SDK Android (pour les versions), JDK, Visual Studio avec les outils Xamarin, NDK, Emulateurs.
Xamarin.iOS Visual Studio avec les outils Xamarin, macOS avec XCode et les SDK's iOS (pour apparayer l'émulateur avec Windows et tester depuis cet OS) ou un compte Apple Developer. XCode avec les SDK's et simulateurs iOS, Visual Studio, Xamarin.
Xamarin.Forms Les deux installations ci-dessus. Les deux installations ci-dessus.

Les outils

  • SDK : Set Development Kit
  • JDK : Java Development Kit
  • NDK : Native Development Kit (C, C++, ...)

Informations complémentaires

Plateformes mobiles natives

Android

  • L'application doit avoir un fichier manifest.xml qui va contenir les informations de l'application (versions d'Android compatibles, nom de l'application, thème, permissions, activités, ...) ;
  • Les ressources sont stockées dans le dossier R et sont indéxées dans une classe pour être utilisées grâce à la méthode view.findById(int).
  • L'application se compose d'une ou plusieurs activités. Les activités ont un cycle de vie (onCreate, onStart, onResume, onPause, onStop, onDestroy, onRestart) ;
  • L'activité de démarrage doit être présicée par la propriété de l'attribut (MainLauncher).

Cycle de vie d'une activité Android

Cycle de vie d'une activité Android

iOS

  • Le point d'entrée de l'application est la classe Application et la méthode statique Main(string[]). La classe UIApplication permet de définir le nom de la classe principale, par défaut AppDelegate.
  • L'AppDelegate permet de définir le comportement global de l'application iOS.
  • On retrouve des ViewController qui vont gérer les interactions entre les différentes "pages".
  • Les fichiers *.storyboard vont définir l'interface graphique de notre application iOS, y compris la navigation.
  • Le fichier info.plist contient les informations relatives à mon application mobile : nom, périphériques, ...

Cycle de vie d'une scène iOS

Cycle de vie d'une scène iOS

Xamarin.Forms

  • Framework qui permet de développer des applications mobiles (natives) sur Android et iOS à l'aide des langages C# (pour le code métier/behind) et XAML (pour l'interface graphique) ;
  • Le point d'entrée est, par défaut, la classe App (fichier App.xaml.cs, qui hérite de Xamarin.Forms.Application) et défini la page de démarrage (Propriété MainPage) ;
  • Le fichier App.xaml contient les ressources (dictionnaires, thèmes, couleurs, ...) globales (accessibles depuis toute l'application) ;
  • Les fichiers *.xaml.cs sont le code behind des pages *.xaml et sont liées à travers la propriété x:Class (côté xaml) ;
  • On peut réutiliser toutes nos connaissances C# pour développer notre application (syntaxe, méthodes, packages NuGet, ...) ;

Cycle de vie d'une application Xamarin.Forms

Cycle de vie d'une application Xamarin.Forms

Xamarin.Forms => iOS & Android ?

Comparaison des cycles de vie d'une application Xamarin.Forms avec une application Android/iOS

Pour chaque événement, un lien est fait entre Xamarin.Forms et Xamarin.Android/Xamarin.iOS. Plus d'informations : https://jlamch.blogspot.com/2018/08/mobile-view-lifecycle-fixing.html

Navigation

(TODO: copier code Mourad)

Bindings

  • Une liaison forte entre un élément et un autre (par exemple, entre un Label et un Slider).
  • Différentes manières de créer une liaison (voir documentation officielle).
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="DataBindingDemos.AlternativeXamlBindingPage"
             Title="Alternative XAML Binding">
    <StackLayout Padding="10, 0">
        <Label Text="TEXT"
               FontSize="40"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"
               Scale="{Binding Value, Source={x:Reference slider},
                               Path=Value}" />

        <Slider x:Name="slider"
                Minimum="-2"
                Maximum="2"
                VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>

Informations complémentaires :

Data Templating

  • Par défaut, une ListView permet d'afficher des éléments et n'a pas de template. Chaque élément aura pour contenu la valeur de la méthode ToString() (soit pour un BlogPost : ExpertsBlog.Entities.BlogPost) ;
  • On peut personnaliser l'UI de chaque élément grâce à un DataTemplate ;
  • Le DataTemplate peut être défini à l'intérieur d'un ItemTemplate (exemple 1) ou dans les ressources d'une page (exemple 2) ou de l'application (fichier App.xaml - exemple 3).

Exemple 1

<ContentPage ...>
<ContentPage.Resources>
    <!--Nothing, empty, nada, rien-->
</ContentPage.Resources>
<RefreshView>
    <CollectionView ItemsSource="{Binding Items}">
        <CollectionView.ItemTemplate>
            <!-- ItemTemplate ne peut prendre qu'un objet de type DataTemplate -->
            <DataTemplate>
                <StackLayout>
                    <Label Text="{Binding Title}"/>
                </StackLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
<RefreshView>
</ContentPage>

Exemple 2

<ContentPage ...>
    <ContentPage.Resources>
        <DataTemplate x:Key="BlogPostTemplate">
            <StackLayout>
                <Label Text="{Binding Title}"/>
            </StackLayout>
        </DataTemplate>
    </ContentPage.Resources>
    <RefreshView>
        <CollectionView ItemsSource="{Binding Items}" ItemTemplate="{StaticResource BlogPostTemplate}"/>
    <RefreshView>
</ContentPage>

Exemple 3

App.xaml :

<Application ...>
    <Application.Resources>
        ...
        <DataTemplate x:Key="BlogPostTemplate">
            <StackLayout>
                <Label Text="{Binding Title}"/>
            </StackLayout>
        </DataTemplate>
        ... 
    </Application.Resources>
</Application>

MainPage.xaml :

<ContentPage ...>
...
    <RefreshView>
        <CollectionView ItemsSource="{Binding Items}" ItemTemplate="{StaticResource BlogPostTemplate}"/>
    <RefreshView>
</ContentPage>

Ne pas confondre l'utilité de RefreshView, ListView et CollectionView.

Pattern MVVM

Pattern MVVM Plus ou moins équivalent au pattern MVC et MVP. Plus d'informations : http://wpftutorial.net/MVVM.html

Rôles

  • View : Afficher les données, retransmettre le ViewModel et envoyer les modifications à effectuer (un champs texte qui envoie une nouvelle valeur au ViewModel) ;
  • ViewModel : Envoyer/Recevoir des données, transformer, notifier un changement à la view (via l'implémentation de l'interface System.ComponentModel.INotifyPropertyChanged) ;
  • Model : Les objets qu'on va manipuler pendant le cycle de vie de notre application (DTO - Data Transfert Object).

Exemple de code

public class DemoViewModel : System.ComponentModel.INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Méthode qui va effectuer la notification
    /// </summary>
    private void OnPropertyChanged(string propertyName)
    {
        // On vérifie que PropertyChanged n'est pas `null`
        if (PropertyChanged == null)
        {
            return;
        }
        // this = instance de `DemoViewModel`
        // Instancier l'événement qui va contenir le nom de la propriété à changer.
        // On créé les arguments de l'événement.
        var args = new PropertyChangedEventArgs(propertyName);
        // On invoque l'événément en lui donnant le nom de la propriété à modifier.
        PropertyChanged.Invoke(this, args);
    }

    /// <summary>
    /// Méthode générique qui va notifier le changement de valeur d'une propriété.
    /// </summary>
    /// <typeparam name="T">Type de la propriété publique et du champ privé.</typeparam>
    /// <param name="storage">Valeur avec sa réference (adresse en mémoire) du champ privé.</param>
    /// <param name="value">Nouvelle valeur.</param>
    /// <param name="propertyName">Le nom de la propriété qui va être modifiée.</param>
    protected void SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        // Vérifier l'égalité entre la valeur de `storage` et de `value`.
        if (EqualityComparer<T>.Default.Equals(storage, value))
        {
            // Si la valeur est égale, on arrête.
            return;
        }
        // On remplace la valeur à l'adresse de `storage` par la nouvelle valeur, `value`.
        storage = value;
        // On appelle la méthode `OnPropertyChanged(string)` qui va créer un événement de changement de valeur.
        OnPropertyChanged(propertyName);
    }
}

INotifyCollectionChanged permet d'être notifié si une collection a été mise à jour ou pas (ajout, édition, suppression, etc). Cette interface est implémentée dans System.ObjectModel.ObservableCollection<T>.

Interface graphique

Shell

Possibilités :

  • Gérer des routes de l'application ;
  • Créer une interface graphique avec soit un menu hamburger (flyout) et/ou des onglets ;
  • Chaque élément peut être modifié grâce aux templates ;
  • Naviguer entre plusieurs pages ;

Ajouter un Shell à mon application :

Créer un Shell :

<Shell xmlns="http://xamarin.com/schemas/2014/forms" 
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:local="clr-namespace:demoshell.Views"
       Title="Demoshell"
       x:Class="Demoshell.AppShell">
    <Shell.Resources>...</Shell.Resources>
        <!-- Element du menu hamburger (flyout), nommé "About" et dont l'icone est spécifiée, permettant de changer de page -->
        <FlyoutItem Title="About" Icon="icon_about.png">
            <ShellContent Route="AboutPage" ContentTemplate="{DataTemplate local:AboutPage}" />
        </FlyoutItem>

        <!-- Element du menu cliquable et qui ne change pas directement le contenu de la page. Cet élément va s'afficher dans le flyout (par défaut, en bas des éventuels `FlyoutItem`) -->
        <MenuItem Text="Logout" Clicked="OnMenuItemClicked" />

        <!-- Barre à onglets, chaque `ShellContent` va représenter un onglet -->
        <TabBar>
            <ShellContent Route="LoginPage" ContentTemplate="{DataTemplate local:LoginPage}" />
        </TabBar>
</Shell>

Enregistrer des routes (non visibles depuis le flyout ou depuis les onglets) :

public partial class AppShell : Xamarin.Forms.Shell
{
    public AppShell()
    {
        InitializeComponent();
        Routing.RegisterRoute(nameof(ItemDetailPage), typeof(ItemDetailPage));
        Routing.RegisterRoute(nameof(NewItemPage), typeof(NewItemPage));
    }

    private void OnMenuItemClicked(object sender, EventArgs e)
    {
        // Do something with menu item.
    }
}

Experts Blog

Une application de blogs spécialisée dans les commerces de proximité.

Structure de la solution

Projet Description
ExpertsBlog.Entities Les modèles (BlogPost, Category, Tag, ) qui serviront à notre API.
ExpertsBlogs.Mobile Le code partagé de l'application.
ExpertsBlogs.Mobile.Android Code spécifique de l'application Android.
ExpertsBlogs.Mobile.iOS Code spécifique de l'application iOS/iPadOS.

Création du projet

  1. Créer un projet Xamarin.Forms (vide) nommé ExpertsBlog.
  2. Implémenter le pattern MVVM.
  3. Modifier la page d'accueil pour afficher une liste de BlogPost.
  4. Modifier le DataTemplate de la liste à afficher.

Ajouter un Shell

  1. Ajouter un fichier à la racine du projet ExpertsBlog.Mobile (template "Forms ContentPage XAML", par exemple) nommé "AppShell" (les fichiers AppShell.xaml.cs et AppShell.xaml vont être créés).
  2. Remplacer la classe parente (héritage) de la classe ExpertsBlog.Mobile.AppShell par Xamarin.Forms.Shell
  3. Remplacer l'élément root du fichier xaml (designer) de ContentPage (ou autre) par Shell.
  4. Modifier la page de démarrage de l'application par une nouvelle instance de AppShell (propriété MainPage du constructeur de la classe App).
  5. Implémenter un Shell avec 2 FlyoutItem qui affiche la liste des billets de blog et "A propos" qui affichera une page "A propos".
  6. Ajouter la page "A propos"
  7. La page principale doit afficher la liste des billets de blog.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages