Exploitation optimale de tous les pixels disponibles : adaptation aux changements d'état d'affichage

Dans Windows 8, vos applications sont exécutées sur des écrans de différentes tailles et dans différents états d'affichage. Ainsi, un utilisateur peut avoir ancré votre application sur le côté d'un écran d'ordinateur de bureau de 25 pouces ou l'afficher en plein écran sur une tablette de 10 pouces. Dans tous les cas, vous souhaitez évidemment que votre application exploite l'intégralité de l'espace d'affichage disponible. Dans ce billet, je vous montre comment vous pouvez détecter, par le biais du code, la taille et l'état d'affichage de votre application. Je vous offre également quelques conseils sur le développement d'applications dans Windows 8 Consumer Preview, de façon à gérer les changements de taille d'écran et d'état d'affichage.

Lors de la conférence //build/, nous avons présenté quelques suggestions relatives à la conception d'applications pour différents scénarios d'affichage (voir par exemple les interventions consacrées au langage XAML et au langage HTML). Plus récemment, sur le blog Conception de Windows 8, nous avons également partagé une partie de nos travaux et de nos réflexions sur la mise à l'échelle en fonction de l'écran. Bien souvent, vous pouvez utiliser du code pur pour adapter l'application aux changements de taille d'écran, sans devoir écrire du code explicite. Dans certains cas cependant, vous devez réaliser un suivi de l'état d'affichage (portrait, plein écran, fenêtre complète, application ancrée, etc.) de votre application et écrire du code pour réagir en conséquence. Par exemple, si vous utilisez un contrôle HTML ListView pour afficher des éléments, il peut être utile d'utiliser un contrôle GridLayout en mode plein écran et un contrôle ListLayout en mode ancré, comme sur l'illustration ci-dessous. En XAML, vous pouvez par exemple basculer de la même façon entre un contrôle GridView et un contrôle ListView. Pour mieux comprendre comment procéder, commençons par examiner comment détecter les redimensionnements et les changements d'état d'affichage dans le code.

La vue complète d'une application de météo affiche trois lignes de trois vignettes, disposées en grille ; à droite, l'écran de la vue ancrée affiche les mêmes vignettes dans une seule colonne

L'écran à l'état Vue complète, à gauche, contient une disposition Grid (HTML) ou un contrôle GridView (XAML) ;
l'écran à l'état Vue ancrée, à droite, contient une disposition List (HTML) ou un contrôle ListView (XAML).

Principes de base des redimensionnements et des changements d'état d'affichage

En matière de gestion des redimensionnements de l'écran et des changements d'état d'affichage, les principes de base sont identiques pour toutes les applications Windows 8, qu'elles soient écrites en XAML ou en HTML : il vous suffit d'attacher des fonctions de rappel aux événements adéquats fournis par les frameworks concernés, puis d'interroger les éventuelles informations nécessaires.

Par exemple, en JavaScript, vous pouvez créer un gestionnaire pour l'événement standard de redimensionnement de fenêtre. Dans ce cas, il s'agit d'une simple fonction de rappel, comme dans l'exemple de code ci-dessous. Vous pouvez utiliser cet événement pour détecter un redimensionnement de la zone d'affichage d'une application et déterminer les nouvelles dimensions de la zone de l'application.

JavaScript

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

window.addEventListener("resize", handleResize);

De même, en XAML, vous pouvez utiliser l'événement SizeChanged dans la fenêtre actuelle pour configurer un gestionnaire d'événements :

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;

Lorsque vous programmez vos applications Windows 8, vous pouvez également utiliser WinRT pour interroger directement l'état d'affichage actuel. WinRT fournit une valeur d'énumération indiquant l'état d'affichage actuel d'une application.

JavaScript

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

C#

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

Les applications Windows 8 écrites en JavaScript prennent également en charge la fonction msMatchMedia, qui fonctionne par le biais de l'objet Window du DOM. Elle peut être utile lorsqu'une condition présente plusieurs requêtes de média (combinaison entre mode paysage en plein écran et largeur d'écran de 1 600 pixels, par exemple) :

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);

Redimensionnement et état d'affichage dans la version Consumer Preview

Maintenant que vous connaissez les principes de base permettant d'accéder à l'état d'affichage et aux informations relatives à la taille de l'écran, examinons comment déployer cette fonctionnalité pour gérer les redimensionnements d'écran. Dans Windows 8 Consumer Preview, l'ordre des événements de redimensionnement et des événements de changement d'état d'affichage est déterministe : les événements d'état d'affichage (et les fonctions de rappel associées) ont toujours lieu avant les événements de redimensionnement. Par conséquent, vous devez toujours attendre le déclenchement de l'événement de redimensionnement avant d'accéder à l'état d'affichage actuel. Vous disposez ainsi d'une approche simple et homogène pour gérer dans votre code les redimensionnements et les changements d'état d'affichage. En attendant ainsi le déclenchement des événements de redimensionnement (et en attendant l'appel des fonctions de rappel associées), vous êtes certain que les informations renvoyées concernant la zone d'affichage actuelle et l'état d'affichage sont synchronisées.

Je vous recommande également d'utiliser des événements de redimensionnement pour déclencher le code chargé de gérer les changements de disposition. En effet, certains événements de redimensionnement d'écran (changement de résolution d'écran, connexion à distance au PC) ne provoquent pas de changement de l'état d'affichage. Par ailleurs, il est judicieux de regrouper au même endroit l'intégralité du code chargé de gérer les changements de disposition, plutôt que d'appeler différents codes pour différents événements de changement d'écran.

Par exemple, supposons que vous souhaitez développer une application qui télécharge des images d'arrière-plan de différentes tailles, selon la résolution actuelle de l'écran. En mode ancré, vous voudrez peut-être télécharger une petite image à afficher en mosaïque à l'arrière-plan, tandis qu'en mode complet, vous préférerez une image standard au format 4:3 ou encore une image 16:9 en mode paysage plein écran. Par ailleurs, selon la hauteur de l'écran, vous voudrez sans doute sélectionner différentes résolutions d'image en fonction de la proportion largeur/hauteur.

En suivant ces conseils, nous avons défini une fonction de rappel basée sur un événement de redimensionnement. Au sein de cette fonction de rappel, nous utilisons une API WinRT pour interroger l'état d'affichage actuel, comme dans l'exemple suivant :

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;

En revanche, si nous souhaitions interroger taille de la zone d'affichage de l'application dans une fonction de rappel déclenchée par un changement d'état d'affichage, nous obtiendrions des informations correctes sur l'état d'affichage, mais avant même que la taille de la zone d'affichage de l'application n'ait été mise à jour. Par conséquent, dans ces circonstances, si notre application est passée du mode ancré au mode paysage plein écran, la valeur AppWidth peut être de 320 pixels, avec une valeur d'état d'affichage fullscreen-landscape. Si nous transmettons ces valeurs à DownloadImage, nous téléchargeons la mauvaise taille d'image.

Les conseils relatifs à l'utilisation des rappels déclenchés par des événements de redimensionnement s'appliquent également à d'autres scénarios. En JavaScript, par exemple, si vous souhaitez modifier la disposition d'un contrôle ListView et la faire passer de Grid à List en fonction de l'état d'affichage, vous pouvez activer le déclenchement d'un rappel au moment du changement d'état d'affichage. Cependant, le fait de définir la disposition ListView avant le redimensionnement de l'écran engendre deux passes de disposition pour le contrôle ListView : une avant le redimensionnement de l'écran et une autre après le redimensionnement. (Le contrôle WinJS ListView gère automatiquement ces événements de redimensionnement, mais pas les événements de changement d'état d'affichage.) Contrairement à l'exemple DownloadImage plus haut, l'utilisateur ne verra peut-être pas directement la différence, mais le temps supplémentaire dont l'application a besoin pour générer la disposition la rend plus lente et moins réactive. Par conséquent, il est préférable d'attendre le rappel lié à un redimensionnement de l'écran avant d'interroger l'état d'affichage actuel et de définir la disposition ListView en conséquence :

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);

Pour XAML, pour basculer d'un état d'affichage à l'autre, utilisez les API VisualStateManager (VSM) pour définir les éléments XAML à afficher dans chaque vue. Si vous utilisez les outils de la version bêta de Visual Studio 2011, vous pouvez découvrir un exemple de ces API défini dans les modèles de projet du modèle Grid App :

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>

Vous remarquerez les groupes VisualState définis pour les différents états d'affichage. Votre code peut ensuite les modifier lorsque l'état a changé dans votre événement SizeChanged :

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);
}

Comme vous pouvez le constater à travers cet exemple, en utilisant VSM et les API SizeChanged et ApplicationView, vous disposez d'un mécanisme extrêmement flexible pour adapter votre application aux changements de disposition d'écran.

Conclusion

Dans ce billet, nous avons examiné comment détecter par le biais du code les événements de redimensionnement d'écran et les changements d'état d'affichage. Pour la version Consumer Preview, je vous recommande d'écouter les événements de changement de taille d'écran avant d'interroger WinRT pour obtenir les informations relatives à l'état d'affichage, comme je l'ai fait ici. Si vous suivez ces conseils, votre code identifiera la taille d'écran actuelle et les informations d'état d'affichage adéquates chaque fois que l'application est redimensionnée. Pour découvrir d'autres exemples, découvrez notre exemple SDK Windows 8. Nous vous invitons également à partager vos réflexions et commentaires à ce sujet !

--Chris Jones, chef de projet, Windows

Je remercie tout particulièrement Tim Heuer, qui m'a aidé à élaborer ce billet.