Wie Sie das meiste aus Ihren Pixeln herausholen – Anpassung an Ansichtsstatusänderungen.

Unter Windows 8 werden Ihre Apps auf Bildschirmen unterschiedlicher Größe und in unterschiedlichen Ansichten ausgeführt. Möglicherweise wird ihre App an der Seite eines 25-Zoll-Desktopbildschirms angedockt, oder sie soll den ganzen 10-Zoll-Widescreenbildschirm eines Tablets ausfüllen. In jedem Fall sollte Ihre App den verfügbaren Platz optimal nutzen. In diesem Beitrag zeige ich Ihnen, wie Sie die aktuelle Größe und Ansicht Ihrer App im Code verfolgen können und gebe Ihnen Tipps zum Schreiben der App in der Windows 8 Consumer Preview, sodass Bildschirmgröße und Ansichtenwechsel optimal verwaltet werden.

Auf der //build/ haben wir Ihnen Anregungen gegeben, wie Sie Ihre App für unterschiedliche Bildschirmszenarien entwerfen können – siehe beispielsweise der XAML-Vortrag oder der HTML-Vortrag. Kürzlich wurden im Blog Die Entwicklung von Windows 8 einige unserer Ansätze bezüglich der Entwicklung und des Designs der Bildschirmskalierung erläutert. Häufig können Sie reines Markup für die Anpassung an wechselnde Bildschirmgrößen verwenden, ohne dass Sie expliziten Code schreiben müssen. Manchmal muss jedoch verfolgt werden, in welchem Ansichtsstatus – Hochformat, Vollbild-, Fenster- oder Andockmodus – sich die App befindet und Code geschrieben werden, der entsprechend reagiert. Wenn Sie zum Beispiel Objekte in HTML mithilfe von ListView anzeigen, ist es möglicherweise besser, im Vollbildmodus GridLayout und im Andockmodus ListLayout zu verwenden, wie in folgender Darstellung. In XAML können Sie entsprechend zwischen einem GridView- und einem ListView-Steuerelement wechseln. Zum besseren Verständnis möchte ich zunächst erläutern, wie Statusänderungen bezüglich Größe und Ansicht im Code erkannt werden können.

In der Vollbildansicht der Wetter-App werden 3 Reihen mit je 3 Kacheln in einer Rasteranordnung angezeigt. In der Andockansicht rechts werden dieselben Kacheln in einer einzigen Spalte angezeigt.

Der Bildschirm in Vollbildansicht links verfügt über ein GridLayout (HTML)- bzw. ein GridView (XAML)-Steuerelement;
der Bildschirm in Andockansicht rechts ein ListLayout (HTML)- oder ein ListView (XAML)-Steuerelement.

Grundlagen zur Änderung von Größe und Ansichtsstatus

Für Änderungen der Größe und des Ansichtsstatus von Windows 8-Apps gilt im Prinzip das gleiche Grundmuster, unabhängig davon, ob sie in XAML als oder in HTML geschrieben werden: Hängen sie einfach Rückruffunktionen an die entsprechenden Ereignisse an, die das jeweilige Framework bereitstellt, und Abfragen für alle erforderlichen zusätzlichen Informationen.

In JavaScript können Sie beispielsweise einen Handler für das grundlegende Fenstergrößenereignis erstellen, bei dem es sich um eine einfache Rückruffunktion handelt, wie im folgenden Codebeispiel. Sie können dieses Ereignis verwenden, um festzustellen, wann der Anzeigenbereich für eine App geändert wurde, und um die neuen Abmessungen des App-Bereichs festzustellen.

JavaScript

 function handleResize(eventArgs) {
    var appWidth = eventArgs.view.outerWidth;
    var appHeight = eventArgs.view.outerHeight;
    ...
}

window.addEventListener("resize", handleResize);

Entsprechend können Sie in XAML das SizeChanged-Ereignis im aktuellen Fenster verwenden, um einen Ereignishandler einzurichten:

C#

 private void OnWindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
    double AppWidth = e.Size.Width;
    double AppHeight = e.Size.Height;
}

Window.Current.SizeChanged += OnWindowSizeChanged;

Beim Programmieren von Windows 8-Apps können Sie auch die WinRT verwenden, um den aktuellen Ansichtsstatus direkt abzufragen. Die WinRT stellt einen Enumerationswert bereit, der Ihnen den aktuellen Ansichtsstatus einer App mitteilt.

JavaScript

 var currentViewState = Windows.UI.ViewManagement.ApplicationView.value;

C#

 var CurrentViewState = Windows.UI.ViewManagement.ApplicationView.Value;

Windows 8-Apps, die in JavaScript geschrieben sind, unterstützen auch die msMatchMedia-Funktion, die über das DOM-Fensterobjekt operiert und nützlich sein kann, wenn mehrere Medienabfragen vorhanden sind, etwa bei der Kombination einer Vollbildansicht im Querformat und einer Bildschirmbreite von 1600 Pixeln:

JavaScript

 var isSnapped = window.msMatchMedia(“(-ms-view-state:fullscreen-landscape) and 
(min-width: 1600px”).matches;

JavaScript

 function handleSnappedMode(mql) {
if (mql.matches) {
        ...
        }
}
window.msMatchMedia(“(-ms-view-state:fullscreen-landscape) and (min-width: 
1600px”).addListener(handleSnappedMode);

Größenänderung und Ansichtsstatus in der Consumer Preview

Sie kennen nun die Grundlagen zum Zugriff auf Informationen über den Ansichtsstatus und die Bildschirmgröße. Ich möchte im Folgenden erläutern, wie diese Funktionalität zum Ändern der Bildschirmgröße verwendet werden kann. In der Windows 8 Consumer Preview ist die Reihenfolge von Größenänderungs- und Ansichtswechselereignissen deterministisch, sodass Ansichtsstatusereignisse (und die damit verbundenen Rückruffunktionen) stets vor Größenänderungsereignissen auftreten. Daher kann auf den aktuellen Ansichtsstatus nur nach dem Auslösen des Größenänderungsereignisses zugegriffen werden. Dies stellt einen einfachen und einheitlichen Ansatz zum Umgang mit Größen- und Ansichtsstatusänderungen in Ihrem Code dar. Durch Abwarten des Auslösens der Größenänderungsereignisse (und aller begleitenden Rückruffunktionen) kann sichergestellt werden, dass die zurückgegebenen Informationen für den aktuelle Anzeigebereich und den Ansichtsstatus synchron sind

Ich empfehle außerdem, dass Sie Größenänderungsereignisse als Auslöser für Code verwenden, der Layoutänderungen verwaltet, da es einige Bildschirmgrößenänderungsereignisse gibt (z. B. Änderung der Bildschirmauflösung oder eine Remoteverbindung zu einem PC), die keine Änderungen im Ansichtsstatus bewirken. Außerdem hat es sich in der Programmierpraxis bewährt, wenn sich der gesamte Code, der Layoutänderungen verwaltet, an der gleichen Stelle befindet, anstatt für alle Bildschirmänderungsereignisse unterschiedlichen Code zu verwenden.

Angenommen, Sie möchten eine App schreiben, die abhängig von der aktuellen Bildschirmauflösung Hintergrundbilder in verschiedenen Größen herunterlädt. Im Andockmodus möchten Sie eine kleines Bild für die Hintergrundkachel herunterladen, im Fenstermodus ein Bild im Standardformat 4:3 oder im Vollbild-Querformat 16:9. Außerdem möchten Sie abhängig von der Bildschirmhöhe unterschiedliche Bildauflösungen für jedes Bildformat auswählen.

Richten Sie nach diesem Muster eine Rückruffunktion ein, die auf einem Größenänderungsereignis basiert, und verwenden innerhalb dieser Rückruffunktion eine WinRT-API, um den aktuellen Ansichtsstatus abzurufen:

JavaScript

 function handleResize(eventArgs) {
    var currentViewState = Windows.UI.ViewManagement.ApplicationView.value;
    var appHeight = eventArgs.view.outerHeight;
    var appWidth = eventArgs.view.outerWidth;

    // downloadImage requires accurate view state and app size!
    downloadImage(currentViewState, appHeight, appWidth);
}

window.addEventListener("resize", handleResize);

 

C#

 private void OnWindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
    var CurrentViewState = Windows.UI.ViewManagement.ApplicationView.Value;
    double AppWidth = e.Size.Width;
    double AppHeight = e.Size.Height;

    // DownloadImage requires accurate view state and app size!
    DownloadImage(CurrentViewState, AppHeight, AppWidth);
}

Window.Current.SizeChanged += OnWindowSizeChanged;

Wird hingegen die Größe des Anzeigenbereichs der App in einer Rückruffunktion abgefragt, die von einer Ansichtsstatusänderung ausgelöst wird, werden zwar die korrekten Informationen über den Ansichtsstatus empfangen, der Anzeigebereich der App ist jedoch noch nicht aktualisiert. Wenn unsere App unter diesen Umständen von der Andock- zur Vollbildansicht im Querformat wechselt, könnte AppWidth 320px betragen und der Ansichtsstatus Vollbildschirm Querformat sein. Wenn wir diese Werte an DownloadImage weitergeben, wird die falsche Bildgröße heruntergeladen!

Die Leitlinien zur Verwendung von Rückrufen, die durch Größenänderungsereignisse ausgelöst werden, treffen auch auf andere Szenarien zu. Wenn Sie beispielsweise in JavaScript das Layout eines ListView-Steuerelements abhängig vom Ansichtsstatus von Raster auf Liste umstellen möchten, können Sie einen Rückruf einstellen, der ausgeführt wird, wenn sich der Ansichtsstatus ändert. Wenn das ListView-Layout jedoch vor der Bildschirmgrößenänderung festgelegt wird, werden für das ListView-Steuerelement zwei Layoutdurchläufe ausgelöst, einer vor der Bildschirmgrößenänderung und einer danach. (Das WinJS-ListView-Steuerelement handhabt Größenänderungsereignisse automatisch, nicht jedoch Ansichtswechselereignisse.) Anders als im DownloadImage-Beispiel von vorhin, würde der Benutzer möglicherweise keinen direkten Unterschied sehen, aber die zusätzliche Zeit, die die App für das Layout benötigt, würde sie langsamer und weniger reaktionsfreudig machen. Es ist also besser, einen Rückruf aufgrund einer Bildschirmgrößenänderung abzuwarten, bevor der aktuelle Ansichtsstatus abgefragt wird, und das ListView-Layout entsprechend einzustellen:

JavaScript

 function handleResize(eventArgs) {
    var isSnapped = (Windows.UI.ViewManagement.ApplicationView.value === 
Windows.UI.ViewManagement.ApplicationViewState.snapped);
    listView.layout = isSnapped ? new WinJS.UI.ListLayout() : new WinJS.UI.GridLayout();
}

window.addEventListener("resize", handleResize);

Um in XAML zwischen den unterschiedlichen Status zu wechseln, verwenden Sie die VisualStateManager (VSM)-APIs, um zu definieren, welche XAML-Elemente zur individuellen Ansicht angezeigt werden sollen. Sollten Sie die Visual Studio 2011 Beta-Tools verwenden, finden Sie ein Beispiel dieser APIs in den Projektvorlagen für die Grid-App-Vorlage.

XAML

 <VisualStateManager.VisualStateGroups>
    <!-- Visual states reflect the application's view state -->
    <VisualStateGroup>
        <VisualState x:Name="FullScreenLandscape"/>
        <VisualState x:Name="Filled"/>

        <!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
        <VisualState x:Name="FullScreenPortrait">
            <!-- definition of what UI elements should display or change would go here in Storyboard 
elements -->
        </VisualState>

        <!-- The back button and title have different styles when snapped, and the list representation 
is substituted for the grid displayed in all other view states -->
        <VisualState x:Name="Snapped">
            <!-- definition of what UI elements should display or change would go here in Storyboard 
elements -->
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

Beachten Sie die VisualState-Gruppen, die für die verschiedenen Ansichtsstatus definiert sind. Ihr Code kann sie dann ändern, wenn sich der Status in Ihrem SizeChanged-Ereignis geändert hat:

C#

 private void OnWindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
    // get the view state after the size has changed
    string CurrentViewState = Windows.UI.ViewManagement.ApplicationView.Value.ToString();
 
    // using VisualStateManager make sure we navigate to the correct state definition
    VisualStateManager.GoToState(this, CurrentViewState, false);
}

Wie Sie an diesem Beispiel sehen können, bietet Ihnen die Verwendung von VSM in Kombination mit den SizeChanged- und ApplicationView- APIs einen flexiblen Mechanismus zur Anpassung an Änderungen des Bildschirmlayouts.

Fazit

In diesem Beitrag ging es darum, wie Sie Bildschirmgrößenänderungsereignisse und Ansichtsstatusänderungen im Code feststellen können. Für die Consumer Preview empfehle ich, wie in diesem Beispiel Bildschirmgrößenänderungsereignisse abzuwarten, bevor die WinRT nach Ansichtsstatusinformationen abgefragt wird. Wenn Sie dieses Muster befolgen, wird Ihr Code bei jeder Größenänderung der App die korrekte aktuelle Größe und die Ansichtsstatusinformationen erkennen. Weitere Beispiele finden Sie im Windows 8-SDK-Beispiel. Bitte teilen Sie uns Ihre Meinung mit, wir freuen uns auf Ihr Feedback zu diesem Thema!

– Chris Jones, Programmanager, Windows

Vielen Dank an Tim Heuer für seine Hilfe beim Erstellen dieses Blogbeitrags.