Mobiele apps programmeren met Xamarin – Device specifiek programmeren

print

Inhoud


Wat vooraf ging


Wat is het probleem?

Het probleem dat ik hier aanhaal is een probleem met iOS die de pagina iets anders opbouwt dan Android of UWP. Om dit te illustreren zou u eigenlijk moeten kunnen uitvoeren naar iOS, maar zelfs al is dit niet het geval de oplossing die ik aanreik kunnen ook voor andere device-gerelateerde problemen gebruikt worden.

  • Start een nieuw Xamarin-project en geef het een passende naam (bv. OpmaakOpMaat).
  • Ga naar MainPage.xaml, u ziet er onderstaande XAML.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:OpmaakOpMaat" x:Class="OpmaakOpMaat.MainPage">

	<Label Text="Greetings, Xamarin Forms!" VerticalOptions="Center" HorizontalOptions="Center" />

</ContentPage>
  • Pas de tekst van het Label aan en verwijder de VerticalOptions en HorizontalOptions zodat de tekst linksboven komt te staan (de aanpassing van de tekst is louter om de onderstaande printscreen te “matchen”).
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:OpmaakOpMaat" x:Class="OpmaakOpMaat.MainPage">

	<Label Text="Greetings, Xamarin Forms!" />
</ContentPage>

Wat is nu het probleem? Wel, als we deze uitvoer zouden bekijken op een iOS-device (iPad, iPhone,…) dan zal u zien dat de tekst te hoog staat en reeds aanwezige tekst overlapt.

Een eerste, eenvoudige, oplossing kan zijn door de Padding aan de bovenrand op bv. 20 pt te plaatsen.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:OpmaakOpMaat" x:Class="OpmaakOpMaat.MainPage">
    <ContentPage.Padding>
        0, 20, 0, 0
    </ContentPage.Padding>

    <Label Text="Greetings, Xamarin Forms!" />

</ContentPage>

Dit zal het probleem oplossen voor iOS maar zal nu de tekst te laag plaatsen voor Android en UWP.

De oplossing zal dus moeten device specifiek geprogrammeerd worden.


Via XAML

Wat er moet gebeuren is de Padding aanpassen. De Padding is eigenlijk van het type Thickness. We kunnen deze afzonderen en platform specifiek maken in XAML. Via OnPlatform:

<OnPlatform x:TypeArguments="Thickness">
</OnPlatform>
  • De volledige code wordt nu:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:OpmaakOpMaat" x:Class="OpmaakOpMaat.MainPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">

        </OnPlatform>
    </ContentPage.Padding>

    <Label Text="Greetings, Xamarin Forms!" />

</ContentPage>
  • Vervolgens kunt u de verschillende platformen specifiëren en de specifieke waarde voor de Thickness per platform (OnPlatform.iOS, OnPlatform.Android, OnPlatform.WinPhone) toekennen:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:OpmaakOpMaat" x:Class="OpmaakOpMaat.MainPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <OnPlatform.iOS>
                0, 20, 0, 0
            </OnPlatform.iOS>
            <OnPlatform.Android>
                0, 0, 0, 0
            </OnPlatform.Android>
            <OnPlatform.WinPhone>
                0, 0, 0, 0
            </OnPlatform.WinPhone>

        </OnPlatform>
    </ContentPage.Padding>

    <Label Text="Greetings, Xamarin Forms!" />

</ContentPage>
  • Omdat er slechts één waarde wordt toegekend (Thickness) kan de code vereenvoudigd worden:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:OpmaakOpMaat" x:Class="OpmaakOpMaat.MainPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" Android="0, 0, 0, 0" WinPhone="0, 0, 0, 0" />
    </ContentPage.Padding>

    <Label Text="Greetings, Xamarin Forms!" />

</ContentPage>
  • En omdat voor Android en WinPhone de standaardwaarde wordt gebruikt en enkel de waarde voor iOS afwijkt kan het nog eenvoudiger door enkel de waarde voor iOS op te nemen:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:OpmaakOpMaat" x:Class="OpmaakOpMaat.MainPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
    </ContentPage.Padding>

    <Label Text="Greetings, Xamarin Forms!" />

</ContentPage>

Via C#

Nu we in een vorige post gezien hebben hoe we pagina’s kunnen bouwen via C# ga ik hier ook even aanhalen hoe u dit in C# kunt bekomen.

Via C# kunt u eveneens de methode Device.OnPlatform() gebruiken. De volledige syntax is:

public static Void OnPlatform (Action iOS, Action Android, Action WinPhone, Action Default)

U merkt dus dat als eerste parameter iOS is, de tweede Android, vervolgs WinPhone (of UWP, Windows dus) en tenslotte een Default waarde.

Als we dit nu toepassen op de Padding door de Thickness in te stellen, dan krijgen we:

Padding = Device.OnPlatform(new Thickness(0, 20, 0, 0), new Thickness(0), new Thickness(0));

Hier bevat de eerste parameter de instellingen voor iOS, de tweede voor Android (met een Thickness van 0 volledig rondom (links, boven, rechts, onder)) en de derde parameter de instelling voor UWP.

of u kunt het ook bekijken van uit de Thickness:

Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);

Hierbij is Links altijd gelijk aan 0, maar de waarde voor de Top is afhankelijk van de device Device.OnPlatform(20, 0, 0) en is 20 op iOS, en 0 voor Android en UWP. Rechts en Onder zijn ook steeds 0.

Tenslotte is er nog een meer, speciale, notatie mogelijk:

Device.OnPlatform(iOS: () =>
{
Padding = new Thickness(0, 20, 0, 0);
});

Of, omdat iOS, de eerste parameter is van de methode Device.OnPlatform():

Device.OnPlatform(() =>
{
Padding = new Thickness(0, 20, 0, 0);
});

De volledige C#-code kan er dus als volgt uitzien:

using System;
using Xamarin.Forms;

namespace OpmaakOpMaat
{
    public class GreetingsPage : ContentPage
    {
        public GreetingsPage()
        {
            Content = new Label
            {
                Text = "Greetings, Xamarin.Forms!"
            };

            Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);
        }
    }
}

of

using System;
using Xamarin.Forms;

namespace OpmaakOpMaat
{
    public class GreetingsPage : ContentPage
    {
        public GreetingsPage()
        {
            Content = new Label
            {
                Text = "Greetings, Xamarin.Forms!"
            };

            Device.OnPlatform(iOS: () => 
            {
                Padding = new Thickness(0, 20, 0, 0);
            });
        }
    }
}

of één van de andere varianten.


In een Shared Project

Hoewel we normaal niet met een Shared Project werken wil ik toch even de oplossing voor zo’n Shared Project aanbieden. De oplossing ligt in het gebruik van preprocessor directives.

using System;
using Xamarin.Forms;

namespace GreetingsSap
{
    public class GreetingsSapPage : ContentPage
    {
        public GreetingsSapPage ()
        {
            Content = new Label
            {
                Text = "Greetings, Xamarin.Forms!"
            };

#if __IOS__

        Padding = new Thickness(0, 20, 0, 0);

#endif
        }
    }
}


Device bepalen

Een andere manier om device specifiek te werken is door gebruik te maken van Device.Idiom. De mogelijke waarden worden bepaald door het TargetIdiom:

  • TargetIdiom.Phone – voor een smartphone.
  • TargetIdiom.Tablet – voor tablet.
  • TargetIdiom.Desktop – voor desktop.
  • TargetIdiom.Unsupported – indien de device niet ondersteund wordt.

Let op dat er met deze methode geen onderscheid gemaakt wordt tussen het besturingssysteem maar tussen het toestel. Dus dit is geen bruikbare oplossing voor het bovenstaande probleem.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:OpmaakOpMaat" x:Class="OpmaakOpMaat.MainPage">
    <ContentPage.Padding>
         <OnIdiom x:TypeArguments="Thickness" Phone="10, 10, 10, 0" Tablet="20, 20, 20, 0"/>
    </ContentPage.Padding>

    <Label Text="Greetings, Xamarin Forms!" />

</ContentPage>

Onderstaand voorbeeld is in C#-code en zal een andere afbeelding laden op een telefoon.

if (Device.Idiom == TargetIdiom.Phone)
{
    MyImage.Source = ImageSource.FromFile("hero.jpg");
} else {
    MyImage.Source = ImageSource.FromFile("herotablet.jpg");
}

Behandelde Basiscompetenties uit de module ICT Programmeren – Specifieke ontwikkelomgeving: complexe functionaliteiten

  • IC BC235 – kan gevorderde principes van programmeren in een specifieke ontwikkelomgeving toepassen
  • IC BC251 – kan een ontwerp in een specifieke ontwikkelomgeving verfijnen
  • IC BC253 – kan broncode in een specifieke ontwikkelomgeving optimaliseren
  • IC BC257 – heeft aandacht voor de gebruiksvriendelijkheid van de toepassing

Geef een reactie

  • Abonneer je op deze website d.m.v. e-mail

    Voer je e-mailadres in om je in te schrijven op deze website en e-mailmeldingen te ontvangen van nieuwe berichten.