Xamarin.Forms

auteur : Solo.

version : 1.0 - 30/08/2020.

1 Divers

1.1 Déverrouillage “http”

Par défaut les application android n’autorise pas la communication avec des sites non sécurisé (qui n’utilisent pas “https”). Pour pallier à cette configuration il faudra modifier le fichier “properties/AndroidManifest.xml”. Objet application du fichier d’origine : <application android:label="PizzaApp.Android" android:theme="@style/MainTheme"></application>

Objet application modifié pour permettre la connexion aux sites “http” : <application android:label="PizzaApp.Android" android:theme="@style/MainTheme" android:usesCleartextTraffic="true"></application>. C’est le paramètre android:usesCleartextTraffic=“true” qui autorise cette connexion. # Style Imposer le même style à des items. L’exemple suivant gère un style pour un bouton. Le style est déclaré dans la fichier : “App.xaml”.

Dans le fichier App.xaml.

<ResourceDictionary>
    <Style TargetType="NavigationPage" ApplyToDerivedTypes="True">
        <Setter Property="BackgroundColor" Value="White" />
        <Setter Property="BarBackgroundColor" Value="#4e89a3"/>
        <Setter Property="BarTextColor" Value="White"/>
    </Style>
    <Style TargetType="ContentPage" ApplyToDerivedTypes="True">
        <Setter Property="BackgroundColor" Value="White" />
    </Style>
    <Style x:Key="boutonLabStyle" TargetType="Button">
        <Setter Property="BackgroundColor" Value="#518faa" />
        <Setter Property="TextColor" Value="White" />
    </Style>
</ResourceDictionary>

Et dans le fichier nomDeLaPage.xaml, la mise en forme est la suivante :

<Button Text="Compter"
    VerticalOptions="Center"
    Clicked="CountButtonClick"
    Style="{StaticResource boutonLabStyle}" />

2 Splash

Afficher une image durant le chargement de l’application.

Dans le fichier Resources/values/styles.xlm :

<style name="splashscreen" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowBackground">@drawable/splash</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsTranslucent">false</item>
    <item name="android:windowIsFloating">false</item>
    <item name="android:backgroundDimEnabled">true</item>
</style>

Les image qui sont représentées dans “@drawable/splash” sont des images “splash.9.png” se trouvant dans les répertoires “drawable”.

Dans le fichier MainActivity.cs il faut rajouté les lignes suivantes :

[Activity(Label = "Pizza", Icon = "@mipmap/icon", Theme = "@style/splashscreen", MainLauncher = true, NoHistory = true)]
public class SplashActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnResume()
    {
        base.OnResume();
        StartActivity(typeof(MainActivity));
    }
}

ATTENTION : Il faut passer à “false” le paramètre “MainLauncher” de “l’Activity” initiale. Et effacer les paramètres “Label” et “Icon” de cette “Activity” iniitiale. # ListView Pour créer une liste, le code suivant doit être incorporé dans la page “nomDeLaPage.xaml” :

<ListView x:Name="maListView" RowHeight="30">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="Center" Margin="15, 0">
                    <Label Text="{Binding Nom}" HorizontalOptions="FillAndExpand" TextColor="Black"/>
                    <Label Text="{Binding Prix}" FontAttributes="Bold" TextColor="Black"/>
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Le code suivant est à intégrer dans le constructeur de la page “nomDeLaPage.cs” :

articles = new List<Article>();
articles.Add(new Article { Nom = "Lait", Prix = "4€", Description = "Pack de 6." });
articles.Add(new Article { Nom = "Chocolat", Prix = "4.85€", Description = "Au lait ou au noisettes." });
articles.Add(new Article { Nom = "Biscuit", Prix = "5.12€", Description = "Ils sont bons." });
articles.Add(new Article { Nom = "Emmental", Prix = "3.5€", Description = "Durée 6 mois." });
articles.Add(new Article { Nom = "Oeuf", Prix = "2.2€", Description = "Paquet de 6." });

maListView.ItemsSource = articles;

maListView.ItemSelected += (sender, e) =>
{
    if (maListView.SelectedItem != null)
    {
        Article article = maListView.SelectedItem as Article;

        DisplayAlert(article.Nom, article.Description, "OK");
        maListView.SelectedItem = null;
    }
};

La classe “Article” est la suivante :

public class Article
{
    public string Nom { get; set; }
    public string Prix { get; set; }
    public string Description { get; set; }
}

3 NavigationPage

3.1 Création d’une navigation

La création d’une navigation se fait dans le fichier “App.xaml.cs”. Il faut remplacer la ligne suivant :

MainPage = new WelcomePage();

par celle-ci :

MainPage = new NavigationPage(new WelcomePage());

IMPORTANT Si on ne veut pas d’une navigation de style “menu”, il faut mettre la ligne suivante dans les codes constructeurs de TOUTES les pages :

// Suppression de la "Navigation Bar"
NavigationPage.SetHasNavigationBar(this, false);

3.2 Appel d’une nouvelle page

Pour appeller une nouvelle page, le code est le suivant :

Navigation.PushAsync(new nomNouvellePage(parametreSiExistant));

Logiquement, dans une compilation classique, “parametreSiExistant” n’existe pas. Si il est nécessaire, il va falloir modifier la ligne d’en-tête du constructeur de la nouvelle page. Un constructeur classique a pour première ligne : public NomPage() Pour un constructeur d’une page demandant un ou des paramètres le code de début du constructeur sera le suivant :

public NomPage() : this(5)
{
}

public NomPage(int parametreSiExistant)

Cela permet de visualiser correctement la page dans le “visualisateur”. ## Retour à la page précédente Pour ce faire, utilisation du code suivant Navigation.PopAsync();. ## Retour à la page initiale Pour ce faire, utilisation du code suivant Navigation.PopToRootAsync();. ## Personalisation de la barre de navigation L’exemple du code suivant donne une possibilité de personnaliser la barre de menu de la navigation.

<NavigationPage.TitleView>
    <StackLayout HorizontalOptions="Center" 
            Margin="{OnPlatform iOS='0,0,25,0', Android='0,0,20,0', Default=0}"
            Orientation="Horizontal">

        <Image Source="pizza_logo.png" HeightRequest="40" />
        <Label Text="Pizzas" 
        FontAttributes="Bold"
        TextColor="White" VerticalOptions="Center" />
    </StackLayout>
</NavigationPage.TitleView>

4 Tache Asynchrone

La création d’une tâche asynchrone s’exécute à partir du code suivant (en exemple) :

private async Task NomDeLaFonction()
{
    await Task.Delay(3000);
    await Navigation.PopToRootAsync();
}

Le mot clé “await” va faire en sorte que chaque ligne s’exécutera lorsque la précédente sera, entièrement, terminée.

Pour info : await Task.Delay(3000); permet d’attendre sans rien faire 3s. # Grid Exemple de création d’un GridLayout :

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <BoxView BackgroundColor="{StaticResource shadowColor}"
                Grid.Row="2"
                Grid.Column="0"
                Rotation="-10"
                Margin="-20, 0, -20, -35"
                HeightRequest="120"/>

    <StackLayout Grid.Row="1" Grid.Column="0" VerticalOptions="Center">
        <Label Text="Devinez le" 
                TextColor="{StaticResource titleColor}"
                FontSize="30" 
                HorizontalOptions="Center"/>
    </StackLayout>
</Grid>

5 JSON

Pour gérer des donner Json il faut intégrer le paquet : Newtonsoft.Json.

Exemple de désérialisation d’une chaine Json contenant un tableau d’objet “Pizza” : pizzas = JsonConvert.DeserializeObject<List<Pizza>>(pizzasJson);. # Téléchargement asynchrone Le code suivant permet à une application de télécharger des datas de façon asynchrone.

public MainPage()
{
    InitializeComponent();

    listView.RefreshCommand = new Command((obj) => {
        DownloadData((pizzas) =>
        {
            listView.ItemsSource = pizzas;

            listView.IsRefreshing = false;
        });
    });

    listView.IsVisible = false;
    waitLayout.IsVisible = true;

    DownloadData((pizzas) =>
    {
        listView.ItemsSource = pizzas;

        listView.IsVisible = true;
        waitLayout.IsVisible = false;
    });
}


public void DownloadData(Action<List<Pizza>> action)
{
    const string URL = "https://drive.google.com/uc?export=download&id=13B0krp-ajtf-SGL9Ia1xKy1lKK2aCq4l";
    using (var webclient = new WebClient())
    {
            // Le téléchargement asynchrone est terminé jusqu'à présent, il ne s'est rien passé...
            webclient.DownloadStringCompleted += (object sender, DownloadStringCompletedEventArgs e) =>
            {
                try
                {
                    string pizzasJson = e.Result;

                    List<Pizza> pizzas = JsonConvert.DeserializeObject<List<Pizza>>(pizzasJson);

                    // La "listView" est un composant graphique, mais à ce niveau, le prog
                    // est dans une thread reseau... d'ou l'appel à : Device.BeginInvokeOnMainThread(()
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        action.Invoke(pizzas);
                    });
                }
                catch (Exception ex)
                {
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        DisplayAlert("ERREUR", "Une erreur réseau s'est produite : " + ex.Message + ".", "OK");
                        action.Invoke(null);
                    });
                }
            };

            // Lancement d'un téléchargement asynchrone
            webclient.DownloadStringAsync(new Uri(URL));
    }
}