• Noser.com
facebook
linkedin
twitter
youtube
  • NOSERmobile
    • Android
    • HTML 5
    • Hybrid Apps
    • iOS
    • Windows Phone
  • NOSERembedded
    • Medizintechnik
  • NOSERprojektmanagement
  • NOSERtesting
  • NOSERlifecycle
    • .NET Allgemein
    • Application Lifecylce Management
    • Apps
    • Architektur
    • ASP.NET
    • Azure
    • Cleancode
    • Cloud
    • Silverlight
    • Visual Studio / Team Foundation Server
    • Windows 8
    • Windows Presentation Foundation
  • NOSERinnovation
    • Big Data
    • Cloud
    • IoT
    • Operations Research
    • Augmented Reality
    • RFID, NFC, Bluetooth LE

Akzente setzen mit der Android Splash Screen API unter .NET MAUI

02. Januar 2023
Rehmann Christoph
0
.NET MAUI, android, Splash Screen, UI
Beitragsbild

Eine Gemeinsamkeit, welche wohl alle Apps verbindet, ist das Vorhandensein eines Startbildschirms bzw. Splash Screen. Oft handelt es sich um ein Vollbild-Layout, welches normalerweise das App Logo und einen einfarbigen Hintergrund anzeigt.

Mit Android 12 hat Google das Splash Screen-Erscheinungsbild vereinheitlicht und eine neue API dafür bereitgestellt. Folgend gehe ich auf diese API ein und zeige, wie man diese unter .NET MAUI nutzen kann.

Der Splash Screen ist keine Werbefläche

Der Splash Screen soll die Ladezeit überbrücken. Zudem soll dieser sofort erscheinen, um dem Benutzer ein direktes Feedback auf seine Interaktion zu geben. Oft verwendet man auch Animationen innerhalb des Splash Screens, um die subjektiv wahrgenommene Ladedauer zu verkürzen.

Wichtig ist, dass man die Anzeigedauer jedoch nicht künstlich verlängert, um etwa das Markenlogo länger präsentieren zu können. Dies entspricht einem Antipattern und sollte vermieden werden.

App Startup States

Um besser zu verstehen, wann der Splash Screen angezeigt wird, ist es wichtig, dass man die App Startup States kennt. Man unterscheidet zwischen drei Typen.

App Startup States

App Startup States

 

Cold Start

Als Cold Start bezeichnet man einen frischen Start der App. Dabei wird der App Prozess gestartet und die App vom Betriebssystem initialisiert. Dies ist zum Beispiel beim ersten Start der App nach einem Geräteneustart der Fall oder wenn die App aufgrund mangelnder Ressourcen vom System zuvor beendet wurde.

Von allen drei Startup States, braucht dieser am längsten und es ist der perfekte Use-Case für den Splash Screen. Hier kann man mit der Anzeige von App-Icon oder Marken-Logo kreativ werden.

Warm Start

Bei einem Warm Start müssen nicht mehr alle Schritte durchlaufen werden wie bei einem Cold Start und der Vorgang ist schneller. Dies ist zum Beispiel der Fall, wenn der Benutzer die App verlässt und anschliessend wieder öffnet. Der Prozess kann im Hintergrund weitergelaufen sein, aber die Anwendung muss die Ansicht von Grund auf neu erstellen.

Ein Startbildschirms wird gegeben falls für sehr kurze Zeit eingeblendet.

Hot Start

Hier entsteht praktisch kein Overhead. Die App und die Ansicht sind bereits im Memory und die App muss das angezeigt UI nicht neu erstellen.

Man sollte keinen Startbildschirms sehen.

Android 12 Splash Screen Verhalten

Standardmässig wird unter Android 12 die im Theme definierte Farbe als Hintergrund für den Splash Screen verwendet und das Launcher Icon in der Mitte angezeigt.

Früher hat man den Splash Screen oft mit Hilfe einer separaten Activity mit eigenem Theme implementiert. Dies steht aber im Konflikt mit dem neuen Verhalten und führt ab Android 12 dazu, dass zuerst der Splash Screen vom System angezeigt wird und anschliessend der eigene Splash Screen folgt. Es ist daher ratsam, dass man von einer solchen Implementation weg migriert.

Um die Darstellung ab Android 12 anzupassen, gibt es unter anderem die zwei neuen Attribute:

<item name="android:windowSplashScreenBackground">@color/..</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/..</item>

Sieht man sich den Source Code von .NET MAUI genauer an, so sieht man, dass diese Attribute dort bereits in Verwendung sind und somit bereits die neuste API genutzt wird. Um ein eigenes Bild auf dem Startbildschirms anzuzeigen, muss man dieses lediglich unter “Resource\Splash” ablegen und mit der Build Action “MauiSplashScreen” versehen. Empfohlen wird ein Bild im SVG-Format, sodass es auch auf unterschiedlichsten Bildschirmgrössen immer optimal skaliert dargestellt werden kann.

Erweiterte Möglichkeiten

Die Startsequenz des Splash Screen lässt sich in drei Teile gliedern:

  1. Enter Animation: Diese bestimmt den Übergang vom System UI zum Splash Screen und wird vom System kontrolliert und kann nicht beeinflusst werden.
  2. Splash Screens Darstellung: Hier hat man zusätzliche Möglichkeiten und es können Animation eingesetzt werden. Weiter ist auch Platz für ein Branding Logo vorgesehen.
  3. Exit Animation: Diese steuert den Übergang vom Splash Screen zum UI der App und kann im Gegensatz zur Enter Animation auch kontrolliert werden.

Splash Screen Icon

Es ist möglich, ein Animated Vectror Drawable (AVD) Icon anstelle eines SVG-Icons zu verwenden. In einem AVD-Icon können sehr einfach entweder einzelne Attribute oder Gruppen von Vektorpfaden animiert werden. Etwa der Alpha-Wert oder auch die Skalierung oder Rotation von Elementen.

AVD-Icons können z.B. mit Adobe After Effects erstellt werden. Es gibt aber auch kostenlose Tools wie etwa die Website Shapeshifter. Diese habe ich in meinem Beispiel Projekt für die Animation des Noser Engineering Logos genutzt.

Noser Logo als AVD

Noser Logo als AVD

Möchte man ein AVD-Icon einsetzen, so muss man dieses im Android Plattform Projekt ablegen.

Visual Studio Solution Explorer

Visual Studio Solution Explorer

Möchte man ein AVD-Icon einsetzen, so muss man dieses im Android Plattform Projekt ablegen. Zudem muss man auch ein eigenes Android Splash Screen Theme definieren:

 <style name="Theme.App.Starting" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@android:color/white</item>
    <item name="windowSplashScreenAnimatedIcon">@drawable/avd_logo</item>
    <item name="windowSplashScreenAnimationDuration">500</item>
    <!-- Set the theme of the Activity that directly follows your splash screen. -->
    <!-- Required -->
    <item name="postSplashScreenTheme">@style/Maui.MainTheme.NoActionBar </item>
</style>

Das hier referenzierte Parent-Theme „Theme.Splash“ stammt aus der AndroidX-SplashScreen Bibliothek. Diese kann man via NuGet mit folgendem Befehl installieren:

dotnet add package Xamarin.AndroidX.Core.SplashScreen

Das windowSplashScreenAnimationDuration Attribut definiert dabei die Zeitdauer der Animation. Dieser Wert ist unabhängig von der Anzeigedauer des Splash Screens. Google empfiehlt diesen Wert unter einer Sekunde zu halten und bei längerer Startup-Zeit auf eine Animations-Schlaufe zu setzen.
Mit dem postSplashScreenTheme Attribut kann man anschliessend noch das Theme referenziert, welches nach der Anzeige des Splash Screens angezeigt wird. Hier kann man das Standard MAUI Theme referenzieren.

Exit Animation

Um die Animation weg vom Splash Screen und hin zum App UI zu kontrollieren, verwendet man ebenfalls die AndroidX-SplashScreen Bibliothek, um einen Listener zu registrieren. Dies muss man in der OnCreate-Methode der MainActivity machen:

protected override void OnCreate(Bundle savedInstanceState)
{
    var splashScreen = InstallSplashScreen(this);
    base.OnCreate(savedInstanceState);

    // Add a callback that's called when the SplashScreen is animating to
    // the app content.
    splashScreen.SetOnExitAnimationListener(this);
}

Durch anschliessendes Implementieren des IOnExitAnimationListener Interfaces, kann man die Exit Animation festlegen. In diesem Beispiel verwende ich eine simple Slide-Up Animation:

public void OnSplashScreenExit(SplashScreenViewProvider splashScreenViewProvider)
{ 
    var slideUp = ObjectAnimator.OfFloat(splashScreenViewProvider.View, nameof(Android.Views.View.TranslationY), 0f, - splashScreenViewProvider.View.Height);
    slideUp.SetInterpolator(new AnticipateInterpolator());
    slideUp.SetDuration(500L);

    // Call SplashScreenView.remove at the end of your custom animation.
    slideUp.AnimationEnd += (args, e) =>
    {
       splashScreenViewProvider.Remove();
    };

    // Run your animation.
    slideUp.Start();
}
Splash Screen mit animiertem Icon und Exit Animation

Splash Screen mit animiertem Icon und Exit Animation

Anzeigedauer verlängern

Android entfern den Splash Screen, sobald die App mit dem Zeichnen des ersten Frames beginnt. Grundsätzlich wird davon abgeraten, den Splash Screen länger als notwendig anzuzeigen. Doch es kann Situationen geben, in diesen man dies trotzdem möchte. Ein Beispiel kann das Sicherstellen von geladenen App-Settings sein. Um dies zu bewerkstelligen kann man einen Listener beim ViewTreeObserver registrieren:

protected override void OnCreate(Bundle savedInstanceState)
{
    // Set up an OnPreDrawListener to the root view.
    contentView = FindViewById<Android.Views.View>(Android.Resource.Id.Content);
    contentView.ViewTreeObserver.AddOnPreDrawListener(this);
     _viewModel.Init();
}

public bool OnPreDraw()
{
    if (_viewModel.IsReady)
    {
        contentView.ViewTreeObserver.RemoveOnPreDrawListener(this);
        return true;
    }
    else
    {
        return false;
    }
}

Fazit

Mit der AndroidX-SplashScreen Bibliothek kann man sehr einfach die Anzeige des Splash Screens kontrollieren. Zudem hat man ab Android 12 auch die Möglichkeit AVD-Icons einzusetzen und so sehr einfach eine Animation einzubinden. Die AndroidX-SplashScreen Bibliothek stellt zwar eine Rückwärtskompatibilität zu älteren Android Versionen sicher, dies beinhaltet aber nicht die Unterstützung von AVD-Icons. Bei älteren Android Versionen werden diese zwar im Splash Screen angezeigt aber nicht animiert.

Möchte man zudem eine gleichen Effekt auch unter iOS erzielen, so muss dies ebenfalls plattformspezifisch umgesetzt werden.

Weitere Ressourcen

  • GitHub Repo mit Beispiel 
  • Android Developers
  • Migrate your existing splash screen implementation to Android 12 and higher | Android Developers
  • Add a splash screen to a .NET MAUI app project – .NET MAUI | Microsoft Learn

SVG Grafiken in Xamarin.Forms verwenden

31. Mai 2019
Rehmann Christoph
0
UX, Xamarin.Forms

Verschiedene Smartphones haben unterschiedlichste Auflösungen. Möchte man sicherstellen, dass alle Icons in seiner App scharf dargestellt werden, muss man diese entweder in unterschiedlichen Auflösungen bereitstellen oder man verwendet skalierbare Vektorgrafiken, wie etwa SVG.

Ausserdem verwenden Android und iOS verschiedene Standards für die Grösse von Icons. Somit müssen diese pro Plattform eingepflegt werden. Dies bedeutet einen zusätzlichen Aufwand.

Doch wenn wir schon Code sowie UI mit Hilfe von Xamarin.Forms zwischen den verschiedenen Plattformen teilen, können wir dann nicht auch gleich die Icons wiederverwenden und wenn möglich gleich in Form von Vektorgrafiken?

Klar, das geht sogar recht gut. Obwohl Xamarin.Forms von sich aus keine SVG Grafiken unterstützt, können diese mit Hilfe von 3rd-party Libraries leicht eingebunden werden.

In einem Projekt, in welchem ich kürzlich gearbeitet habe, verwendete ich dazu FFImageLoading und SkiaSharp. Beide Libraries wurden bereits im Projekt benutzt, sodass nur noch das NuGet Package von Xamarin.FFImageLoading.Svg.Forms hinzugefügt werden musste. SkiaSharp ist eine Cross-Platform 2D-Grafik Library, welche auf der Skia-Grafikbibliothek von Google basiert.

FFImageLoading

FFImageLoading ist eine viel verwendete Library, wenn es darum geht Bilder aus dem Internet herzunterzuladen und anzuzeigen. Sie bietet eine Vielzahl von Funktionen wie etwa:

  • Caching von Bildern
  • Wiederholtes herunterladen von Bildern bei Fehlern
  • Darstellung von Platzhalterbildern, wenn der Download fehlschlägt
  • Skalierung und Transformierung von Bildern

Beispielanwendung

Ich habe ein kleines Demo-Projekt erstellt, in welchem ich zum einen lokal eingebundene SVG-Grafiken anzeige aber auch solche aus dem Internet.

FFImageLoading installieren und initialisieren

Als erstes muss FFImageLoading via NuGet zum Xamarin.Forms- sowie den Plattformprojekten hinzugefügt werden. Dies macht man entweder via NuGet Package Verwaltung oder einfach über die Konsole:

dotnet add package Xamarin.FFImageLoading.Svg.Forms --version 2.4.11.982

Um verwendet werden zu können, muss FFImageLoading beim Starten der App initialisiert werden. Am besten macht man dies noch vor der Initialisierung von Xamarin.Forms in der MainActivity oder im AppDelegate.

SVG Grafiken einbinden

Beim Hinzufügen von SVG Dateien zum Projekt, muss man darauf achten, dass man die Build Action auf “Embedded resource” stellt.

Property Window

Aus Editoren exportiere SVG Grafiken enthalten oft viele redundante und nutzlose Informationen. Das können zum Beispiel Editor-Metadaten, Kommentare, ausgeblendete Elemente und Standardwerte sein. Diese können entfernt werden, ohne dass die Darstellung beeinträchtigt oder verändert wird. Dazu nutzt man am besten ein Tool wie etwa SVGO.

Die Grafiken können anschliessend direkt per Xaml eingebunden werden:

<ffimageloadingsvg:SvgCachedImage 
    Grid.Column="0" Grid.Row="0"
    WidthRequest="200" HeightRequest="200"
    ErrorPlaceholder="resource://XamarinFormsSvgSample.Resources.outline-warning-24px.svg"
    FadeAnimationForCachedImages="True"
    FadeAnimationEnabled="True"
    FadeAnimationDuration="100"
    Source="{Binding Item.IconUrl}" />

In diesem Beispiel verwende ich für den ErrorPlaceholder eine lokal hinterlegte SVG Grafik und als Source eine Url zu einem SVG im Internet.

Fazit

Mit FFImageLoading und SkiaSharp kann man auf sehr einfache Weise SVG Grafik in seine Xamarin.Forms App einbinden. Dadurch muss man seine Icons nicht für jede Plattform separat einpflegen. Weiter kann die Grösse der App verringert werden, da man nicht mehr dasselbe Icon in unterschiedlichen Auflösungen ausliefern muss. Allerdings muss man beachten, dass die Darstellung von SVG Grafiken etwas mehr Rechenleistung verlangt. Besonders in Zusammenhang mit einer ListView und mehreren SVG Grafiken pro Eintrag konnte ich beobachten, dass das Scrollen zum Teil etwas stockt. Bei der Verwendung von SVG Grafiken in der Toolbar oder in Tabs konnte ich jedoch keine Performance-Einbussen feststellen.

1234567

Tag Cloud

.NET android Angular AngularJs Arduino ASP.Net automated testing Azure Big Data C# C++ Cloud continuous integration Elm Embedded Führung gRPC Internet of Things IoT Java Javascript M2M OWASP Projektmanagement protobuf Python Raspberry Pi Reactive Programming REST Scrum Security Softwarequalität SPA Testen testing Testmanagement Teststrategie UX Visual Studio WebAPI windows WPF Xamarin Xamarin.Android Xamarin.Forms

Archive

Current Posts

  • Akzente setzen mit der Android Splash Screen API unter .NET MAUI
  • Do You have Your Personal Space?
  • Automated provisioning with ARM Templates
  • Asynchrone Beobachtungen und Versprechungen in Angular
  • Simplify Your Automated Tests With Fluent Syntax

Last Comments

  • Hans Reinsch bei Der Safety-Plan: Die wichtigsten Antworten mit Checkliste
  • George H. Barbehenn bei Modeling Optocouplers with Spice
  • Noser Blog Touch-Actions in Xamarin.Forms - Noser Blog bei Mach mehr aus Animationen in Xamarin.Forms mit SkiaSharp
  • Noser Blog Focus on the Secure Storage service of Trusted Firmware (TFM) - Noser Blog bei First run of the Trusted Firmware (TFM) application
  • Noser Blog First run of the Trusted Firmware (TFM) application - Noser Blog bei Focus on the Secure Storage service of Trusted Firmware (TFM)

Popular Posts

Xamarin.Android Code Obfuscation

6 Comments

ManuScripts: Wenn jemand eine Reise tut... Funktionale Programmierung mit Elm - Teil 1 - Aufbruch

5 Comments

ManuScripts: Wenn jemand eine Reise tut... Funktionale Programmierung mit Elm - Teil 2 - Kein Picknick

4 Comments

Contact us

  1. Name *
    * Please enter your name
  2. Email *
    * Please enter a valid email address
  3. Message *
    * Please enter message
© 2013 NOSER ENGINEERING AG. All rights reserved. Datenschutz | Cookie-Richtlinie