Blog

Kontextsensitive User Interfaces mit der Universal Windows Platform

David Würfel
David Würfel
17. Juni 2015

Vor kurzem habe ich auf der dotnet Cologne und auch auf der DWX Developer Week einen Vortrag mit dem Titel „4K und andere Herausforderungen – Next Generation Desktop UIs für Windows 10“ gehalten. Der Vortrag hat den Begriff der Universal App Platform auf Windows 10 beleuchtet und was ein Entwickler dieser entlocken kann, um zukunftsorientierte User Interfaces umzusetzen. Folgender Blogbeitrag soll nicht nur diejenigen erreichen, die meine Session besuchen konnten, sondern auch diejenigen, die nicht vor Ort waren. Der Artikel soll darüber hinaus noch tiefergehende Informationen zur Thematik liefern. Analog zu meiner Session, in der es gegen Ende einen Live-Coding-Teil gab, wird es auch hier schließlich Code geben, wobei ein paar der neuen Universal App Features exemplarisch zu sehen sind.

Rückblick auf Windows 8

Windows 8 Startbildschim

Windows 8 Startbildschim (Quelle: Microsoft News Center)

One UI to rule them all, das war der Eindruck, den Windows 8 im Jahr 2012 wohl bei den meisten Anwendern vermittelte. Die neue touch-orientierte, grelle Kacheloberfläche und das fehlende Startmenü stellten für viele Nutzer einen starken Konsistenzbruch dar. Für den Endbenutzer weniger sichtbar, tat sich zu der Zeit auch aus Entwicklersicht einiges. Im Sinne der Platform Convergence Journey wurde mit Einführung von Windows 8 der Betriebssystem-Kernel zwischen Xbox, Windows 8 und Windows Phone 8 vereinheitlicht. Mit Windows 8.1 wurde dann das App-Modell zusammengeführt. Bereits damals war es unter dem Begriff Universal App schon möglich eine Windows Store App mit einer App Identität und möglichst gleicher Codebasis für Desktops und Smartphones zu erschaffen, wenn auch etwas umständlich.

Platform Convergence Journey

Platform Convergence Journey (Quelle: Screencapture Microsoft Virtual Academy)

Die Windows 10 Philosophie

Windows 10 Desktop und Startmenü

Windows 10 Desktop und Startmenü (Quelle: Microsoft News Center)

Mit Windows 10 erscheint es zunächst so, als gehe Microsoft wieder einen Schritt zurück. Aus Sicht eines Desktopnutzers ist dies sicherlich richtig. Windows Store Apps können im Fenster laufen, es gibt wieder ein klassisches Startmenü in Verbindung mit einigen Kacheln und Touchbedienung ist nun nicht mehr der Standardfall. Nur wenn Windows beispielweise auf einem Tablet läuft, wird das UI spezifisch angepasst. Aus Entwicklersicht geht man jedoch weiterhin einen konsequenten Weg in Richtung Vereinheitlichung: Künftig gibt es keine Trennung mehr von Windows Versionen für verschiedene Geräte. Das Windows 10 wird auf allen Geräten gleichermaßen laufen, ob Smartphone, Desktop, Xbox, Surface Hub und sogar HoloLens oder IoT Geräte wie der RaspberryPi. Unter der sogenannten Universal Windows Platform wird auch eine künftige Windows App auf allen Geräten gleichermaßen laufen – und dies im Sinne von write once, deploy everywhere.

Universal Windows Platform

Universal Windows Platform (Quelle: Microsoft Blog)

Der Entwickler entwickelt fortan eine App – wirklich ein Binary – welche auf allen Geräten veröffentlicht wird und direkt lauffähig ist. Dies soll jedoch auf keinen Fall bedeuten, dass die Anwendung auf allen Geräten gleich erscheint. Vielmehr sollen die Entwickler die UI an die verschiedenen Endgeräte anpassen, sei es eine Smartwatch, eine mobile Line-of-Business App, eine Desktop-Anwendung oder ein UI für eine Kühlschranksteuerung im Internet of Things. Durch das MVVM Pattern und eine saubere Schichtentrennung ist dies sehr gut möglich, da sich die interne Geschäftslogik von der austauschbaren, anpassbaren und hochoptimierten Darstellungsschicht trennen lässt.

MVVM: Model-View-ViewModel Softwareschichtung

MVVM: Model-View-ViewModel Softwareschichtung

Spezialisierte UIs

Wie sieht nun diese Spezialisierung aus? Wo und welche Anpassungen sind für verschiedene Geräte nötig? Welche Mittel bieten sich mir als Entwickler meine UI anzupassen? Wie filtere ich technisch verschiedene Geräteklassen und nehme diesbezüglich Anpassungen vor?

Die intuitivste Komponente, die einem in den Sinn kommt, wenn man an verschiedene Geräte denkt, sind die verschiedenen Formfaktoren, wie Displaygröße, Auflösung und daraus resultierend die physikalische – sprich vom Gerät gegebene – Pixeldichte. Nicht zu vergessen ist in diesem Zusammenhang auch die Entfernung zum Betrachter: der Sichtabstand. Um dies kurz zusammen zu fassen, kann man sagen, eine höhere physikalische Auflösung auf kleinerer physikalischer Bildschirmdiagonalen bedeutet eine höhere Pixeldichte, auch PPI (pixel per inch) genannt. Diese wird umso wichtiger, je näher der Betrachter dem Gerät ist. Daher sind hochauflösende Displays bei Smartphones keine Besonderheit mehr. Man kann höhere PPI nutzen, um entweder mehr Inhalt auf gleicher Fläche unterzubringen, was nur bis zu einem bestimmten Grad sinnvoll ist, oder man kann gleichen Inhalt in besserer Qualität darstellen. Runde Formen, die auf digitalen Geräten immer nur Annäherungen sind, können so ihrer Idealdarstellung immer näher kommen. Für den Nutzer erscheint die Anwendungsoberfläche dann crisp und smooth.

Es reicht oft aber nicht, nur diese Faktoren zu betrachten. Mit dem aus dem Web stammenden Responsive Design unterscheidet man beispielsweise Desktop und Smartphone anhand der Auflösung und macht beispielsweise zweispaltigen Inhalt einspaltig, zeigt nur noch die essentiellen Inhalte an oder verschiebt sie in sekundäre Navigationslevel. Dies ist ein erster Schritt, der jedoch schnell an seine Grenzen stößt. Responsive Design ist relativ technisch motiviert und berücksichtigt zunächst nur Geräteparameter. Bezieht man beim UX Design die Benutzerrolle und den aktuellen Nutzungskontext mit ein, kommt man zu deutlich besseren, intuitiveren Ergebnissen. Diese essentielle Berücksichtigung des Nutzers nennt sich kontextsensitives Design.

Kontextsensitives Design

Microsoft HoloLens

Microsoft HoloLens (Quelle: Microsoft News Center)

Extrembeispiele, die von kontextsensitivem Design profitieren wären beispielsweise Anwendungen für Virtual Reality und Augmented Reality Geräte. Denn was bedeutet der Begriff Auflösung für diese Geräteklassen? Für eine VR-Brille ist eine hohe Auflösung in erster Linie wichtig damit der Benutzer kein störendes Fliegengitter vor seinem Auge erkennt, schließlich ist das Display in sehr geringem Abstand davor. Viel wichtiger ist an dieser Stelle die wahrgenommene Auflösung und wie das UI in der 3D-Szene der VR- oder AR-Anwendung platziert ist. Wie in Microsofts Keynote der Build 2015 zu sehen, könnten zum Beispiel UI Elemente im realen Raum platziert werden. Mit klassischem Responsive Design lässt sich solch eine Herausforderung nur schlecht lösen.

Microsoft HoloLens: Konzept einer Augmented Reality Anwendung

Microsoft HoloLens: Konzept einer Augmented Reality Anwendung (Quelle: Microsoft News Center)

Dabei genügt es bereits sich, allein den Desktop – also ein stationärer Rechner – zu betrachten, sei es ein Büro-PC, ein Konferenzmonitor oder ein großer Screen in einer Leitwarte einer Raumstation. Auch hier kommt man schnell in Situationen, die mit Responsive Design allein nicht zu lösen sind.

Kontrollraum der esa Raumstation

Kontrollraum der esa Raumstation (Quelle: esa Homepage)

Es gibt so manche Entwickler, die mit Monitoren in hochkant-Ausrichtung arbeiten. Gibt es Anwendungen, die darauf eingehen, ob der Monitor hochkant gestellt wurde? Pair-Programming Sessions oder walkthrough-artige Codereviews finden mit mehreren Personen vor einem Bildschirm statt. Dabei stehen manche Personen eventuell näher am Bildschirm, andere weiter weg. Welche Anwendungen berücksichtigen diese Szenarien?

Ein typischer Desktop?

Ein typischer Desktop?

Microsofts Surface Hub ist ein riesiger Konferenzbildschirm mit 84 Zoll, mehreren Kameras, ausgerichteten Mikrofonen und Stifteingabe. Der Präsentator steht direkt vor dem Gerät und kann über einen Stift direkt in Anwendungen zeichnen, viele Betrachter sitzen in einiger Entfernung und beobachten das Geschehen und es können sogar Teilnehmer nur remote zugeschaltet sein, die aber gleichen Inhalt auf Ihrem heimischen PC sehen. Bisher ist mir keine Meeting-Anwendung bekannt, die ohne Umstellungen auf solch einen Fall optimiert wäre.

Microsoft Surface Hub in Meetings

Microsoft Surface Hub in Meetings (Quelle: Microsoft News Center)

Solche Herausforderungen, die sich breit ausgerichteten Universal Apps stellen, können nur durch kontextsensitives Design auf dem UI gelöst werden. Dabei kennt die Anwendung ihren Nutzungskontext und reagiert dementsprechend. Durch im Gerät vorhandene Eye-Tracking-Sensoren könnte der Sichtabstand des Betrachters erkannt und Anwendungen dementsprechend angepasst werden. Eine App weiß, ob sie auf einem hochkant ausgerichteten Monitor läuft und optimiert Ihren Inhalt auf dieses Szenario. Erst wenn das Gerät über ein Mikrofon als Eingabegerät verfügt, wird beispielsweise Push-To-Talk-Funktionalität eingeblendet. Es gibt hier zahlreiche Herausforderungen, die nur gut gelöst werden können, wenn man den Nutzer nicht aus den Augen verliert. Aus technischer Sicht hört sich das für einen Entwickler jedoch nach sehr viel Zusatzarbeit an. Das Auslesen von Eye-Tracking Informationen und darauf reagierende Layout- und Inhaltsoptimierungen erscheinen wie eine Herkulesaufgabe. Der Entwickler bekommt mit Windows 10, Visual Studio 2015 und der Universal App Platform neue Features, die eine gute Unterstützung bieten, um kontextsensitive Software mit guter User Experience entwickeln zu können. Im Folgenden sollen ein paar dieser Werkzeuge betrachtet werden.

UWP Features unter Windows 10

Wie schon in WPF die device independent pixels, geht Microsoft bei der UWP einen Schritt weiter in Hinsicht eines abstrakten Pixelbegriffs und führt die sogenannten effective pixels ein. Diese basieren auf der Pixeldichte des Gerätes und eines heuristischen Sichtabstands. Daraus ergibt sich eine abstrakte Pixelinformation, sodass der Entwickler sich nicht mehr um diese physikalischen Details kümmern muss. Auf allen Geräten erscheinen dem Betrachter demnach die Elemente in gleicher Größe.

Weiterhin gibt es mit dem RelativePanel einen neuen Layoutcontainer, der es recht einfach möglich macht, die Elemente innerhalb des Containers in Relation zueinander anzuordnen. Das ist besonders hilfreich, wenn sich das Layout dynamisch verhalten soll. Musste man früher ein Custom-Panel implementieren oder recht komplexe Umstellungen eines Grids durchführen, so kann man nun das RelativePanel verwenden.

Um auf verschiedene Geräteklassen und Formfaktoren zu reagieren, wollen wir uns im Folgenden die sogenannten VisualState-Trigger etwas genauer anschauen. Der von Microsoft vorgeschlagene Weg für ein adaptives Layout ist die Verwendung des VisualState-Managers und VisualStates für unterschiedliche Zustände der View.

Beispielimplementierung: Ein eigener VisualState-Trigger

Stellen wir uns einmal folgendes Szenario vor: Der Nutzer besitzt einen Monitor mit der Möglichkeit den aktuellen Sichtabstand zu messen (z.B. über eine Webcam, ein Headtracking-System, Infrarot, die Kinect o.ä.). Als Entwickler einer Anwendung möchte ich nun, dass die Schrift in meiner Anwendung auf den Sichtabstand des Betrachters angepasst wird. Diese sollte für ihn immer gleich groß erscheinen. Ob er nun sehr nah am Bildschirm (weil er z.B. Notizen mit einem Stift auf einem touch-sensitiven Monitor macht), in normalen Abstand davor oder in einer Pair-Session in etwas Entfernung davon sitzt. Als UI Entwickler möchte ich diese Änderung technisch „erkennen“ können, um anschließend in XAML recht einfach darauf zu reagieren. Dies soll nun beispielhaft umgesetzt werden. Dabei liegt der Fokus weniger auf der Ausarbeitung einer schönen und vollständigen Anwendung als vielmehr darauf, die zur Verfügung stehenden Features zu demonstrieren.

Zunächst erstellen wir ein neues Windows Universal App Project, öffnen dort die MainPage.xaml und platzieren unseren Text dort. Gleichzeitig führen wir examplarisch zwei Visual States ein, für den nahen und fernen Sichtabstand:

<Grid Margin="25" Background="White">
   <VisualStateManager.VisualStateGroups>
      <VisualStateGroup x:Name="CommonStates">
         <VisualState x:Name="Near">
            <!-- Trigger and reaction missing for now. -->
         </VisualState>
         <!-- Here could be more states … -->
         <VisualState x:Name="Far">
            <!-- Trigger and reaction missing for now. -->
         </VisualState>
      </VisualStateGroup>
   </VisualStateManager.VisualStateGroups>
   <TextBlock x:Name="Output"
      FontSize="20"
      Text="Lorem ipsum dolor sit amet, consetetur…"
      TextTrimming="CharacterEllipsis"
      TextWrapping="Wrap" />
</Grid>

 

Momentan ist der AdaptiveTrigger der einzige Trigger, den Microsoft mitliefert. Damit ist es lediglich möglich, auf die Größe des Bildschirms (gegeben in effective pixels) zu reagieren. Es gibt zunächst keine Möglichkeit auf die hier gestellten Anforderungen zu reagieren. Glücklicherweise können wir jedoch eigene Trigger schreiben und diese in XAML benutzen. Wir wollen beispielweise in unseren Near-State wechseln, sobald die ViewDistance 12 Zoll unterschreitet und dies per Trigger folgendermaßen abbilden:

<VisualState x:Name="Near">
   <VisualState.StateTriggers>
      <triggers:ViewDistanceTrigger MaxViewDistance="12" />
   </VisualState.StateTriggers>
   <!-- What to do? -->
</VisualState>

 

Dieser Trigger muss nun implementiert werden. Dazu kann man von StateTriggerBase ableiten und innerhalb der Klasse über die Methode SetActive diesen (de)aktivieren. Der im XAML definierte VisualState wird aktiv, sobald SetActive(true) im aufgerufen wird.
Der Trigger könnte beispielsweise eine Komponente IViewDistanceDetector benutzen, welche für die Erkennung des Sichtabstands zuständig ist:

public class ViewDistanceTrigger : StateTriggerBase
{
   public double MinViewDistance { get; set; } = 0;
   public double MaxViewDistance { get; set; } = double.PositiveInfinity;

   private IViewDistanceDetector viewDistanceDetector;

   public ViewDistanceTrigger()
   {
      viewDistanceDetector = new ViewDistanceDetector();
      viewDistanceDetector.ViewDistanceChanged +=
	     ViewDistanceDetector_ViewDistanceChanged;
   }

   private void ViewDistanceDetector_ViewDistanceChanged
      (object sender, ViewDistanceChangedEventArgs eventArgs)
   {
      double currentViewDistance = eventArgs.ViewDistanceInInch;
   
      if((currentViewDistance >= MinViewDistance)
	     && (currentViewDistance <= MaxViewDistance))
      {
         SetActive(true);
      }
      else
      {
         SetActive(false);
      }
   }
}

 

Der Einfachheit wollen wir an dieser Stelle lediglich die FontSize unseres TextBlocks ändern. Mit den neuen Setters im VisualState ist diese diskrete Änderung sogar ohne komplexe Definition von Storyboards möglich. Ein Feature was vor allem bei initialen Zustandswechseln hilfreich ist:

<VisualState x:Name="Near">
   <VisualState.StateTriggers>
      <triggers:ViewDistanceTrigger MaxViewDistance="12" />
   </VisualState.StateTriggers>
   <VisualState.Setters>
      <Setter 
         Target="Output.FontSize"
         Value="{StaticResource FontSize.Small}" />
   </VisualState.Setters>
</VisualState>
<VisualState x:Name="Far">
   <VisualState.StateTriggers>
      <triggers:ViewDistanceTrigger MaxViewDistance="25" />
   </VisualState.StateTriggers>
   <VisualState.Setters>
      <Setter 
         Target="Output.FontSize"
         Value="{StaticResource FontSize.Large}" />
   </VisualState.Setters>
</VisualState>

 

Selbstverständlich wären ein animierter, flüssiger Übergang und noch mehrere Zwischenzustände hier wünschenswert. Um jedoch sehr knapp zu zeigen, wie man in einer Universal App eigene Trigger schreibt und kontextsensitive Anpassungen am UI vornimmt, sollte das an dieser Stelle genügen. Selbstverständlich kann dieses Konzept auf eine Reihe anderer kontextbezogener Informationen ausgeweitet werden: Ist mein Monitor hochkant orientiert? Habe ich ein Mikrofon zur Spracheingabe zur Verfügung? Ist ein Xbox Controller an meinem Gerät angeschlossen? Läuft meine Anwendung auf einer bestimmten Geräteklasse? All diese Informationen könnte man komfortabel in solche Trigger auslagern. Zu hoffen ist auch, dass Microsoft noch weitere eigene Trigger mitliefert und den Entwicklern einen Teil des Implementierungsaufwands abnimmt.

Fazit

Windows 10 und die Universal App Platform liefern uns – wie eben gezeigt – Hilfsmittel, die UI für verschiedene Endgeräte zu optimieren. Wenn Microsoft verspricht, dass eine App auf allen Geräten gleichermaßen laufen soll, müssen sie dies auch tun. Andererseits kann man diese Tools auch nutzen, um schon allein das Desktop-Erlebnis seiner Anwendung zu optimieren. Erkenntnisse bezüglich verschiedener Nutzungsszenarien und –rollen, die man bei der Entwicklung von Smartphone UIs kennengelernt hat, kann man auch auf den Desktop übertragen. Auch in stationären Umgebungen gibt es eine Vielzahl von Kontexten und unterschiedlichen Interaktionsmöglichkeiten auf die jeweils geeignet reagiert werden muss. Der Desktop ist, was das UX Design betrifft, in vielen Fällen noch nicht am Ende angekommen. Hier verstecken sich noch viele innovative Konzepte. Diese sollte man entdecken, nutzen und am Ende durch eine herausragende Anwendung beeindrucken.

Download

Wer meine Session zu Next Generation Desktop UIs für Windows 10 noch ein Mal anhand der Vortragsfolien nachvollziehen möchte, kann das hier tun. Ich stelle auch gerne die Code Samples von der Live Demo auf der DWX und Code Snippets aus diesem Blogbeitrag zum Download:

Alle auf dieser Webseite erwähnten Marken- und Warenzeichen oder Produktnamen sind Eigentum ihrer jeweiligen Inhaber und dienen nur der Beschreibung.

Möchten Sie mehr zu unseren Leistungen, Produkten oder zu unserem UX-Prozess erfahren?
Wir sind gespannt auf Ihre Anfrage.

Senior UX Manager
+49 681 959 3110

Bitte bestätigen Sie vor dem Versand Ihrer Anfrage über die obige Checkbox, dass wir Sie kontaktieren dürfen.