Xamarin.Forms 1.3 bringt Lifecycle-Unterstützung, Styles, Trigger und Behavior

Xamarin.Forms hat mit den Neuerungen der kürzlich freigegebenen Version 1.3 einen großen Schritt in Richtung einer ernstzunehmenden Alternative zur nativen App-Entwicklung gemacht.

vorlesen Druckansicht
Lesezeit: 5 Min.
Von
  • Waldemar Cichon
Inhaltsverzeichnis

Kürzlich erreichte die Version 1.3 des plattformübergreifenden C#-Framework Xamarin.Forms auch die Benutzer des sogenannten Stable-Channels des aus der Mono-Entwicklung hervorgegangenen Softwareherstellers. Für einen lediglich die Minor-Versionsnummer betreffenden Versionssprung weist das neue Release unerwartet viele bedeutende neue Features auf, wie einem Webinar des Unternehmens zu entnehmen ist.

Eine größere Neuerung betrifft die seit der Vorstellung des Frameworks im vergangenen Frühjahr von vielen gewünschte Unterstützung des Lebenszyklus einer App. Das Update enthält Handler für drei Lifecycle-Ereignisse: OnStart, OnSleep sowie OnResume. Hier ein Beispiel, wie sich die Handler einsetzen lassen:

public class App : Xamarin.Forms.Application
{
public App ()
{
MainPage = new ContentPage { Title = "Sample Page" };
}
protected override void OnStart()
{
// Handle when your app starts
Debug.WriteLine ("App starts");
}
protected override void OnSleep()
{
// Handle when your app sleeps
Debug.WriteLine ("Before sleeping");
}
protected override void OnResume()
{
// Handle when your app resumes
Debug.WriteLine ("Resuming");
}
}

Ein weiteres Feature stellen Styles dar. Mit ihnen lassen sich Komponentengruppen einfach verändern, die in einer XAML-Datei definiert werden. Eigenschaften wie Farbe, Größen, Schatten, Ränder, Ausrichtungen und Ähnliches werden damit zentral an einer Stelle festgelegt. Somit erlaubt die Vorgehensweise einerseits ein wesentlich schnelleres Festlegen eines einheitlichen Look & Feel einer Applikation, da alle Vorgaben nur noch zentral zu pflegen sind. Das erspart dem Programmierer andererseits das langwierige Suchen und Ändern an diversen Stellen, sollten sich die Vorgaben mal ändern. Ein Beispiel:

<!--?xml version="1.0" encoding="UTF-8"?-->
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="StylesApps.MyPage">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="HorizontalOptions" Value="FillAndExpand"/>
<Setter Property="BackgroundColor" Value="#77d065"/>
<Setter Property="BorderColor" Value="Black"/>
<Setter Property="HeightRequest" Value="42"/>
<Setter Property="BorderRadius" Value="5"/>
<Setter Property="BorderWidth" Value="0" />
<Setter Property="TextColor" Value="White"/>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="10" Spacing="10">
<Button Text="Login" Style="{StaticResource ButtonStyle}" />
<Button Text="Logout" Style="{StaticResource ButtonStyle}"/>
<Button Text="Register" Style="{StaticResource ButtonStyle}"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>

Trigger dienen dazu, unter Zuhilfenahme der Styles das Aussehen bestimmter Komponenten in Abhängigkeit vom Inhalt eines Eingabefeldes oder beim Eintreffen bestimmter Ereignisse zu verändern. Dieses wird rein deklarativ in der XAML-Datei festgelegt und erfordert keinerlei Programmierung. Im folgenden Beispiel unterhalb wird die Schrift ein wenig vergrößert und grün gefärbt, solange das Feld den Fokus besitzt:

<!--?xml version="1.0" encoding="UTF-8"?-->
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="StylesApps.MyPage2">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="EntryTrigger" TargetType="Entry">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True"
TargetType="Entry">
<Setter Property="Scale" Value="1.1" />
<Setter Property="TextColor" Value="Green" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="20" Spacing="10">
<Entry Placeholder="Username" Style="{StaticResource
EntryTrigger}" />
<Entry Placeholder="Password" Style="{StaticResource
EntryTrigger}"/>
<Button Text="Login" />
</StackLayout>
</ContentPage.Content>
</ContentPage>

Behaviors dienen der einfachen Anpassung des Verhaltens bestimmter Komponenten ohne die Notwendigkeit, diese zu überschreiben. Dieses soll zu einer erhöhten Flexibilität bei vermindertem Programmieraufwand und zu weniger Fehlern führen. Ein Behavior ist letztlich eine Klasse, die von der Basisklasse Behavior abgeleitet wird und zwei Methoden (OnAttachedTo und OnDetachingFrom) überschreibt, wodurch dann seine Event-Handler an die Komponente gebunden beziehungsweise die Bindung gelöscht werden:

public class EmailValidatorBehavior : Behavior
{
const string emailRegex = @"^(?("")("".+?(?<!\\)""@)|
(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)
(?<=[0-9a-z])@))" + @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])
|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]
{0,22}[a-z0-9]))$";
static readonly BindablePropertyKey IsValidPropertyKey =
BindableProperty.CreateReadOnly("IsValid", typeof(bool),
typeof(NumberValidatorBehavior), false);
public static readonly BindableProperty IsValidProperty =
IsValidPropertyKey.BindableProperty;
public bool IsValid
{
get { return (bool)base.GetValue(IsValidProperty); }
private set { base.SetValue(IsValidPropertyKey, value); }
}
protected override void OnAttachedTo(Entry bindable)
{
bindable.TextChanged += HandleTextChanged;
}
void HandleTextChanged(object sender, TextChangedEventArgs e)
{
IsValid = (Regex.IsMatch(e.NewTextValue, emailRegex,
RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250)))
? true : false;
((Entry)sender).TextColor = IsValid
? Color.Default : Color.Red;
}
protected override void OnDetachingFrom(Entry bindable)
{
bindable.TextChanged -= HandleTextChanged;
}
}

Die Bindung an die Komponente geschieht dann gewöhnlicherweise nicht im Programmcode, sondern in der XAML-Datei.

<Entry Grid.Row="0"
Grid.Column="1"
Placeholder="Email" >
<Entry.Behaviors>
<local:EmailValidatorBehavior x:Name="emailValidator"/>
</Entry.Behaviors>
</Entry>
<Image Grid.Row="0"
Grid.Column="2"
x:Name="emailSuccessErrorImage"
Style="{Binding Source={x:Reference emailValidator},
Path=IsValid,
Converter={StaticResource boolToStyleImage}}"/>

Des Weiteren sind noch einige Layout- und Geschwindigkeitsverbesserungen Bestandteil von Xamarin.Forms 1.3. Die Bibliothek hat damit einen großen Schritt in Richtung einer Alternative zur nativen Entwicklung gemacht. Einzig ein brauchbarer UI-Editor fehlt noch, um die Entwicklung wirklich effektiv, schnell und einfach vorantreiben zu können.

Siehe dazu auf heise Developer:

(ane)