Single Blog Title

MTC BLOG

MobileTech Conference | Konferenz für Mobile Marketing, Development & Business
MobileTechCon | 13. - 16. März 2017, München

5 Dec 2016

GUI nach Maß
Xamarin hat im Laufe der letzten Jahre eine rapide Entwicklung durchgemacht: Aus der .NET Runtime für Unix wurde ein veritables Cross-Plattform-System, das mit Xamarin.Forms sogar einen eigenen plattformunabhängigen GUI-Stack anbietet.

Trotz der reichhaltigen Möglichkeiten von Xamarin.Forms gibt es immer wieder Situationen, in denen man lieber auf die nativen Steuerelemente der jeweiligen Hostplattform zurückgreift. Außerdem gibt es keine offizielle Möglichkeit, Xamarin.Forms-Formulare in einem WYSIWYG-Editor zu bearbeiten – auf die diversen Workarounds wollen wir an dieser Stelle nicht weiter eingehen. Darüber hinaus gibt es immer wieder Steuerelemente von Drittanbietern, die nur in einer bestimmten Umgebung lebensfähig sind. Werbesysteme sind ein klassischer Problemfall, der Cross-Plattform-Entwicklern schon einmal graue Haare verpasst.

Kurz gefasst: Es gibt eine Vielzahl von Gründen für komplett native Benutzerschnittstellen. In diesem Fall schlägt die Stunde der in Xamarin Studio bzw. in Visual Studio verbauten Designerprogramme, die die Arbeit erheblich erleichtern.

Aktualisierung von Visual Studio

Wer auf seiner Workstation eine ältere, also vor der Build 2016 heruntergeladene, Version von Visual Studio verwendet, sollte seine IDE auf die aktuellste Version –Update 2 – aktualisieren. Microsoft bietet ein Programm an, das die (auch auf schnellen Workstations eine gute Stunde dauernde) Aktualisierung automatisch vornimmt. Achten Sie darauf, die aktuellste Version von Xamarin durch manuelle Auswahl mit zu installieren. Je nach Systemkonfiguration kann es vorkommen, dass das Installationsprogramm das Paket „vergisst“.

Klicken Sie nach dem obligaten Neustart auf New Project, und erzeugen Sie ein neues Projekt vom Typ Visual C# | Android | Blank App. In den folgenden Beispielen wird vom Projektnamen „GUITest“ ausgegangen.

Bevor wir uns der eigentlichen Erstellung von Benutzerinterfaces zuwenden, noch eine kleine Erklärung zum Hintergrund. Android arbeitet mit im XML-Format vorliegenden Steuerelementen bzw. Formularen, die zur Laufzeit von einem Extraktor in Klassenhierarchien umgewandelt werden.

Auch wenn man Steuerelemente theoretisch zur Laufzeit erzeugen und einfügen kann, entstehen die meisten Formulare aus Layoutdateien, die während der Programmausführung maximal um Kleinigkeiten erweitert werden. Die Zusammenstellung der Layoutfiles erfolgt – je nach Fasson des Entwicklers – entweder von Hand in einem an Webdesign erinnernden Prozess, oder durch verschiedene Generatoren.

Aber nun los

Android-erfahrene Entwickler bemerken in Abbildung 1 einen kleinen Unterschied im Ordnerlayout: Die Layoutdatei heißt hier Main.AXML, anstatt wie normalerweise eine gewöhnliche XML-Datei zu sein. Dieser Unterschied ist durchaus relevant. XML-Dateien können mehrere Versionen einer Ressource enthalten und sind somit nicht mit den für normale .xml-Dateien vorgesehenen Werkzeugen kompatibel.

Nach dem Öffnen via Doppelklick erscheint aufgrund suboptimaler Zoomeinstellungen in der Regel lediglich ein graues Rechteck auf der oberen Seite des Bildschirms. Dieses Problem lässt sich durch Anklicken der Portrait- oder Landscape-Buttons beheben. Nach Anklicken der Knöpfe sollte das Formular ungefähr wie in Abbildung 1 gezeigt aussehen.


Abb. 1: Das von Microsoft vorgegebene Formular ist nicht besonders komplex

Die auf der rechten Seite des Bildschirms befindliche Toolbox bietet eine Liste von Steuerelementen an, die sich per Drag and Drop beliebig auf dem Bildschirm platzieren lassen. Wir wollen fürs Erste einen weiteren Knopf einfügen: Er liegt in der Kategorie „Button“, und fügt sich beim Einbauen automatisch unter dem schon vorhandenen „Hello-World“-Knopf ein. Das liegt daran, dass Android-Formulare so gut wie immer automatisch gelayoutet werden.

Die Navigation durch Formulare geht besonders bequem von der Hand, wenn man eine baumartige Ansicht der Inhalte des Layouts hat. Diese wird von Xamarins Android Designer von Haus aus nicht angezeigt, lässt sich aber durch Anklicken von View | Other windows | Document outline oder das Drücken von CTRL + ALT + T auf den Bildschirm holen.

Richtig bequem lässt es sicher immer dann arbeiten, wenn man die Toolbox öffnet und das herumschwebende Document-Outline-Fenster unter ihr andockt. Auf diese Art und Weise entsteht auf der linken Seite des Bildschirms ein kombiniertes Fenster aus Toolbox und Dokumentenoutline, das bei der Bearbeitung hilfreich ist.

Um diesen Sachverhalt nachzuvollziehen, wollen wir den Quellcode des Formulars betrachten. Klicken Sie auf den Source-Tab, um den XAML-Code aus Listing 1 auf den Bildschirm zu holen.

Das in Listing 1 gezeigte Codesnippet ist insofern interessant, als dass es die Verwendung von Ausbreitungsattributen demonstriert. Das Layoutsystem analysiert den zur Verfügung stehenden Bildschirmplatz zur Laufzeit und weist den einzelnen Widgets je nach Verfügbarkeit Platz zu.

Wir sehen in Listing 1 gleich mehrere Attribute: match_parent übernimmt die Dimension des Elternelements, während wrap_content den minimal nötigen Platz zur Darstellung der Inhalte einnimmt. Mittels fill_parent weist man das Steuerelement dazu an, den maximal möglichen Platz einzunehmen.

Für das Zuweisen dieser Attribute müssen Sie nicht unbedingt in die Codeansicht wechseln. Wer die einzelnen Widgets im Editor markiert, sieht neben den bekannten Drag-Controllern auch die in Abbildung 2 und Abbildung 3 aufgeschlüsselten Pfeile. Wer sie anklickt, setzt das Skalierungsverhalten der jeweiligen Achse automatisch auf den gewünschten Wert.


Abb. 2: Nach außen zeigende Pfeile aktivieren die Option “Match Parent” (Bildquelle: Xamarin)

Abb. 3: Nach innen zeigender Pfeil versetzt Steuerelement in Wrap-Content-Modus (Bidlquelle: Xamarin)

Abermaliges Anklicken des Steuerelements ersetzt die Vergrößerungssteuerelemente durch die in Abbildung 4 gezeigten Pulleys. Sie erlauben das Festlegen der Breite der Margins, die dem von Haus aus zugewiesenem Platz zusätzlichen Raum abziehen.


Abb. 4: Margins lassen sich direkt aus dem Editor heraus konfigurieren (Bildquelle: Xamarin)

Smarter Knopf

Data Binding ist unter Android nur sehr rudimentär implementiert. Das Zuweisen von Event Handlern erfolgt normalerweise zur Laufzeit. Unser Projektskelett führt dies im Code Behind vor – OnCreate weist dem Click-Event des Knopfs einen Delegaten zu, der den auszuführenden Code bereitstellt (Listing 2).

Xamarin Studio greift von XAML verwöhnten Entwicklern an dieser Stelle unter die Arme – im auf der unteren rechten Bildschirmkante eingeblendeten Properties-Feld gibt es einen Wert onClick, dessen Nutzung allerdings etwas Umdenken voraussetzt. Doppeltes Anklicken des Felds öffnet den für uns derzeit nicht relevanten Ressourcenselektor. Geben Sie stattdessen den Wert susWelcome ein.

Zur Nutzung des Handlers müssen Sie im Code-Behind eine Methode anlegen, die von Xamarin zur Laufzeit mit dem Steuerelement verdrahtet wird. Im Fall des Namens susWelcome sieht der dazu notwendige Code wie in Listing 3 aus.

Android Event Handler werden immer mit einem Zeiger auf das für die Auslösung zuständige Steuerelement ausgeliefert. Das ist insofern interessant, als dass Android-Entwickler einen Event Handler gerne mit mehreren Widgets verdrahten. Wundern Sie sich also nicht, wenn onPuberLevitating für eine ganze Kohorte von Sprayern verantwortlich ist.

Export weist den in Xamarin integrierten Compiler dazu an, die betreffende Methode für Java sichtbar zu machen. Das ist wichtig, da das Fehlen der passenden Funktion zur Laufzeit zu einem Absturz des GUI-Stacks führt. Für die Nutzung der in Java.Interop beheimateten Exportierfunktion ist das Hinzufügen einer Referenz auf die Assembly Mono.Android.Export.dll erforderlich. Diese lässt sich wie jeder andere Assembly-Verweis einpflegen.

Damit ist das Programm auch schon für die Ausführung bereit. Klicken Sie auf den Play-Knopf in der Toolbar, um die Kompilation anzuwerfen. Die Virtual Machine (VM) „Xamarin_ANDROID_API_23“ erwies sich in den Tests des Autors als am unproblematischsten. Im Rahmen des ersten Starts konstruiert Visual Studio eine virtuelle Maschine, wozu etwas Zeit erforderlich ist.

Fehlersuche

Googles Android-Emulator erweist sich unter Windows mitunter als zickig; paradoxerweise treten Probleme immer dann gehäuft auf, wenn die Basishardware extrem leistungsfähig ist. Als erste Gegenmaßnahme ist ein Windows-Neustart zwingend erforderlich.

Funktioniert die VM danach noch immer nicht, sollten sie von Hand gestartet werden. Zur Fehlersuche eignet sich das von Google bereitgestellte AVD-Verwaltungstool.

Wählen Sie im nächsten Schritt das problematische AVD – die Abkürzung steht übrigens für Android Virtual Device – aus, und öffnen Sie seine Eigenschaften über den Edit-Button. Bei auf x86-Technologie basierenden virtuellen Maschinen ist es mitunter hilfreich, die Option „Use Host GPU“ zu deaktivieren. Wer den Microsoft-eigenen Android-Emulator benutzt, findet unter stack overflow eine Liste von häufigen Fehlerquellen.

Reißen alle Stricke, so bietet sich die Nutzung realer Hardware an. Aus Platzgründen können wir an dieser Stelle darauf nicht weiter eingehen. Versetzen Sie das jeweilige Telefon in den Entwicklermodus und verbinden Sie es mit dem Rechner.

Fragmentierung

Fragmentierung ist ein hässliches Wort. Schon zu Zeiten von Palm OS und Windows Phone gab es verschiedene Smartphonearten, da jeder Nutzer seine eigene Handgröße und seine eigenen Bedürfnisse mitbrachte. Der eine brauchte einen möglichst großen Bildschirm, während der andere zur Bearbeitung von E-Mails eine Tastatur und aufgrund des kleineren Bildschirms einen geringeren Akkuverbrauch bevorzugt hat.

Der immense Erfolg des iPhone brachte Handcomputern Medienaufmerksamkeit. Schlecht informierte Journalisten brachten Fragmentierung auf; das Buzzword geistert seitdem wie ein losgelassener Heißluftballon durch die Welt.

Android ist von Haus aus gut auf das Handhaben von Fragmentierungssituationen vorbereitet. Entwickler weisen das Betriebssystem dazu an, eine Ressource aus einer XML-Datei wiederzubeleben. Das Betriebssystem sucht die XML-Datei dabei anhand des übergebenen Namens aus. Was genau passiert, ist ein vergleichsweise komplexer und hochinteressanter Prozess.

Die Dateinamen bzw. Ordnerpfade von Ressourcen sind keine reinen Strings. Als Beispiel dafür betrachten wir die folgende Struktur, die aus einer praktischen Applikation entnommen wurde:

main.xml liegt hier in drei Versionen vor. Die im Ordner layout liegende Datei repräsentiert den „Standard“. -ar ist der stärkste Qualifikator: Ein arabisches Telefon würde immer die im Unterordner layout-ar liegende Variante laden. ldrtl dient als „Catch-All-Qualifikator“. Ist das Smartphone nicht auf Arabisch eingestellt, weist aber eine LTR-Sprache auf, so wird diese Datei geladen.

Will man eine App beispielsweise mit zwei verschiedenen Layouts für den Portrait- und den Landscape-Mode ausstatten, so ist das kein besonderes Problem. Man legt einfach zwei verschiedene Versionen der XML-Datei an und überlässt dem Betriebssystem die Qual der Wahl.

Wir wollen diese Aufgabe nun unter Nutzung von Xamarin Designer für Android realisieren. Das unter Android Studio zur Verfügung stehende Ordnerkonstruktionswerkzeug ist in Visual Studio nicht implementiert. Öffnen Sie die Datei Main.axml stattdessen im Editor, und klicken Sie das Telefonsymbol neben dem Label „Device“ einige Male an.

Xamarin Designer reagiert darauf mit dem Einblenden der Versionsliste, die im Moment nur „Default“ anbietet. Klicken Sie auf New Version, um die Microsoft-Version des Generators zu erzeugen – Abbildung 5 zeigt die richtige Konfiguration.


Abb. 5: Setzen des Landscape-Qualifiers erzeugt für Landscape-Mode geeignetes Formular.

Mit nativen Android-IDEs erfahrene Entwickler müssen an dieser Stelle umdenken. Im Solution Explorer erscheint anfangs nur eine .axml-Datei – die „Unterversionen“ scheinen, wenn überhaupt, erst nach einem Kompilationsvorgang auf.

Zur Demonstration des Verhaltens ergänzen wir das Formular um ein zweites LinearLayout, das die beiden Buttons nebeneinander anordnet. Die Umordnung geht im Outlinefenster am bequemsten von der Hand – speichern Sie das File, wenn Sie mit den Resultaten zufrieden sind. Der Bildschirm des Emulators lässt sich durch Betätigen von CTRL + F11 in den Landscape-Mode versetzen – falls Sie sich davon überzeugen wollen, dass das Programm korrekt funktioniert.

Bei der Arbeit mit verschachtelten Layouts hilft Xamarin Designer mit Komfortfeatures aus. Das mit Abstand wichtigste ist der Layouthervorheber, dessen Aktivierung die Abstände zwischen den Steuerelementgruppen erhöht. Zudem öffnet ein Rechtsklick auf ein Steuerelement eine Liste von Einträgen, die das Auswählen der Elternlayouts erlauben.

Zu guter Letzt gibt es mit der Option „Multi-edit“ die Möglichkeit, mehrere Varianten des Layouts gleichzeitig zu bearbeiten. Dies spart insbesondere dann Zeit, wenn größere Änderungen am Gesamtaufbau erforderlich sind.

Effizientere Lokalisierung

Als der Autor dieser Zeilen noch ein junger Spund war, veröffentlichte der damals in IT-Kreisen bekannte Eric Sink einen Blogbeitrag zur Lokalisierung. Der Tenor: Es lohnt sich nicht; meine japanische Lokalisierung bringt etwa so viel ein wie ich im Monat für Sushi ausgebe.

Dank dem Aufkommen von App Stores und der damit einhergehenden Flut von Apps ist Lokalisierung heute wesentlich wichtiger. Wenn man schon für das Wort „Aeroplane“ keinen Topplatz in der Liste erreichen kann, geht es ja vielleicht mit „авиационный“ (Russisch), uçak (Türkisch) oder aviadilo (Esperanto).

Rein theoretisch könnte man die Internationalisierung von Android-Apps über das Anbieten von Layoutfiles erledigen. Das wäre allerdings insofern ineffizient, als dass ein Großteil des XML-Codes „nutzlos“ verfiele. Eine bessere Möglichkeit ist die Einführung einer Abstraktionsebene. Die Layoutdateien enthalten dabei statt der darzustellenden Strings reduzierte String-IDs, die vom System während der Programmausführung durch in der jeweiligen Systemsprache gehaltene Texte ersetzt werden. Diese finden sich in so genannten String-Dateien, die per Konvention normalerweise strings.xml heißen.

An dieser Stelle rächt sich das Nichtvorhandensein des weiter oben erwähnten Verzeichniskonstrukteurs: Es gibt keine grafische Unterstützung für die Erzeugung von Varianten der Datei strings.xml. Erstellen Sie deshalb einen weiteren Ordner namens values-de, in den sie die Datei strings.xml unter Beibehaltung der Build-Action „Android Resource“ kopieren. Passen Sie ihren Inhalt folgendermaßen an:

Zum Test der Applikation können Sie den Emulator wie ein normales Smartphone ins Deutsche umwandeln – der Text erscheint ab dem nächsten Start auf Deutsch.

Testing

Das größte Problem bei der Arbeit mit Ressourcenvarianten ist das Testen aller möglichen Permutationen. Die weiter oben zum Setzen eines vernünftigen Zoomfaktors zweckentfremdeten Landscape- und Portrait-Mode-Buttons bieten ein Menü an, mit dem sich die vom Designer gerenderte Variante anpassen lässt.

Auf der linken oberen Kante des Bildschirms finden sich weitere Optionen. Das Devicedialogfeld erlaubt die Auswahl des Telefons, das für das Rendering der Vorschau verwendet werden soll. Wie unter Android Studio funktioniert das Übernehmen der Bildschirmgröße im Allgemeinen gut, während das Einstellen der plattformspezifischen Rendering-Engine nicht immer funktioniert.

Material Design

Das Material Design ließ in Sachen GUI-Design keinen Stein auf dem anderen: Google nutzte das Update für radikale Veränderungen. Eine wichtige Regel ist die Empfehlung, Steuerelemente in einem fixen Gitter anzuordnen – der Xamarin Designer unterstützt diese Arbeit durch das in Abbildung 6 gezeigte Positionierungsgitter.


Abb. 6: Steuerelemente richten sich wie von Geisterhand automatisch aus

Ein weiteres Feature findet sich hinter dem Pfeil: Xamarin unterstützt auch die Erzeugung der für die Festlegung der Steuerelementfarben zuständigen Themes mit einem dedizierten Werkzeug. Weitere Informationen dazu finden sich in dieser Dokumentation, zu deren Verständnis aber Hintergrundwissen über das Gesamtkonzept des Material Designs notwendig ist.

Fazit

Der in Xamarin Studio eingebaute Android Designer erleichtert Entwicklern die Arbeit mit Layoutfiles – was den Komfort anbetrifft ist er durchaus mit dem in Android Studio integrierten Werkzeug vergleichbar. Das bedeutet allerdings nicht, dass man als .NET-Entwickler nun freudig drauflos programmieren kann. Kenntnisse des Android-GUI-Systems sind nach wie vor erforderlich; der Code lässt sich zudem nicht unter iOS oder Windows Phone weiterverwenden.

Wer wahre Cross-Plattform-Applikationen erzeugen möchte, muss stattdessen auf das in der Einleitung erwähnte Xamarin.Forms setzen.