Accueil

21
Sep 11

Tutoriel WP7 : Accent Color et dérivées

Un des points forts du dernier OS mobile de Microsoft, c’est la gestion de l’Accent Color. Cette petite bête qui permet à l’utilisateur de personnaliser son téléphone avec sa couleur préférée.

Selection d'une Accent Color - Credits Microsoft

Les éléments importants de l’interface sont donc mis en avant grâce à l’Accent Color. Inutile de préciser qu’il vaut mieux éviter de mettre d’autres couleurs fixées dans le code, au risque que l’utilisateur ai choisi une Accent Color similaire. Il ne verrait plus grand chose.

Mais l’œil appartient à la physique et si on souhaite ajouter d’autres couleurs il est possible de calculer celles qui s’adapteront le mieux, selon votre œil, à l’Accent Color de l’application. On pourra alors utiliser soit la couleur inverse qui sera la couleur contrastant le plus avec l’Accent Color, soit la couleur complémentaire qui est la couleur la plus agréable à l’œil face à l’Accent Color. On obtient donc au final deux couleurs qui s’accordent entre elles dans votre design.

Couleur complementaire

Comment calculer ces couleurs? Adobe a eu la bonne idée de nous donner les formules sur son site : http://adobe.ly/nF5WXx

Cet article va donc vous aider a mettre en place ces formules dans vos projets Silverlight et XNA pour ainsi utiliser tout le potentiel des Accent Colors liées aux Contrast Accent Colors et Complementary Accent Colors.

Icone

Gestion en Silverlight.

Pour commencer, ouvrez votre outil favoris qui est Visual Studio puis créez un projet Windows Phone Application. Une fois ouvert, ajouter une classe Tools.cs (ou autre, l’important est de connaitre le nom du namespace pour pouvoir utiliser ces fonctions dans le reste de votre code). C’est cette classe qui va contenir les fonctions utiles pour récupérer nos couleurs depuis n’importe où dans l’application.

Accent Color

L’accent color est la couleur la plus simple à obtenir en Silverlight. Elle est accessible directement depuis les ressources de l’application sous forme de SolidColorBrush.

On peut y acceder directement dans le XAML :


//ou encore

Ou dans le code behind :

Color accentColor = ((SolidColorBrush)Application.Current.Resources["PhoneAccentBrush"]).Color;

Il n’est donc pas nécessaire de s’en occuper dans notre classe Tools, mais il est important de savoir la récupérer pour calculer les autres couleurs.

Contrast Accent Color

C’est ici que l’on commence à effectuer des calculs. Comme l’explique Adobe, pour obtenir la couleur inverse, ou contrast color, il faut prendre la valeur opposée de chaque valeur RVB qui composent notre couleur. Par exemple avec R la valeur rouge, on prendra 255-R. En code cela donne ceci :

        public static Color GetAccentContrastColor()
        {
            Color accentColor = ((SolidColorBrush)Application.Current.Resources["PhoneAccentBrush"]).Color;

            Color contrastColor = new Color()
            {
                R = (byte)(255 - accentColor.R),
                G = (byte)(255 - accentColor.G),
                B = (byte)(255 - accentColor.B),
                A = (byte)255
            };

            return contrastColor;
        }

On reconstruit tout un objet Color grâce aux différentes valeurs de l’accent color. Celles si ayant été préalablement soustraites à 255.

Complementary Accent Color

Pour la couleur complémentaire, ou Complementary Color, c’est un peu différent. Le calcul est le même que pour la couleur inverse mais au lieu de prendre 255 on prend la somme de la plus grande valeur RVB avec la plus petite valeur RVB.

         public static Color GetAccentComplementatyColor()
        {
            Color accentColor = ((SolidColorBrush) Application.Current.Resources["PhoneAccentBrush"]).Color;

            byte maxValue = Math.Max(accentColor.R, accentColor.G);
            maxValue = Math.Max(maxValue, accentColor.B);

            byte minValue = Math.Min(accentColor.R, accentColor.G);
            minValue = Math.Min(minValue, accentColor.B);

            byte sumValues = (byte) (maxValue + minValue);

            Color complementaryColor = new Color() {
                R = (byte)(sumValues - accentColor.R),
                G = (byte)(sumValues - accentColor.G), 
                B = (byte)(sumValues - accentColor.B),
                A = (byte)255
            };

            return complementaryColor;
        }

Ici le helper Math est très utile pour trouver les minimum et maximum des valeurs RVB.

Utilisation

Maintenant que notre classe est construite vous allez devoir modifier votre projet pour pouvoir l’utiliser.

Ouvrez App.xaml.cs et ajoutez dans son constructeur :

// Add brushes for contrast and complementary colors based on accent color.
Resources.Add("AccentComplementaryColor", Tools.GetAccentComplementatyColor());
Resources.Add("AccentContrastColor", Tools.GetAccentContrastColor());

Il vous suffira alors d’utiliser ces ressources dans votre code XAML:

            
                
            
                
            
                
            

Et le designer?

Vous aurez surement remarqué que même si le code fonctionne à la compilation, la couleur reste transparente dans le designer de Visual Studio. C’est normal car le constructeur de App.xaml.cs n’est pas appelé. Pour corriger ce problème, ajouter un dictionnaire de ressources en ajoutant un fichier XML au projet appelé DesignDictionary.xaml. Mettez y un et ajoutez dedans ces brushes :


	
    
    

Elles correspondent aux couleurs calculées pour la couleur par defaut du designer : le bleu.

Allez dans App.xaml et ajoutez y le dictionnaire précédemment créé.

        
            
                
            
        

Maintenant votre designer se basera sur les resources du dictionnaire, mais celles-ci seront écrasée par les vrais valeurs calculées à l’exécution du programme.

Icone

Gestion en XNA.

Dans Visual Studio créez un nouveau projet de type Windows Phone Game (4.0) et ajoutez votre classe Tools.cs.

Avant de rajouter notre code il va falloir rajouter deux références importantes :

using Microsoft.Xna.Framework;
using System.Windows;

Microsoft.Xna.Framework nous permettra d’accéder à la classe Color compatible avec notre jeu.
System.Windows nous permettra d’accéder à la classe Application du téléphone et de récupérer son Accent Color. Pour pouvoir ajouter cette référence, il faut aller dans l’arborescence du projet, effectuer un click droit sur le dossier Resources puis selectionner Add Reference, dans la liste qui s’affiche, prenez System.Windows.

Maintenant, place au code !

Commençons par la fonction de récupération de l’Accent Color. Par defaut cette propriété n’est pas disponible en XNA, il faudra donc passer par le namespace System.Windows (d’ou l’ajout de sa référence un peu plus haut) et aller chercher dans les ressources de l’application la propriété PhoneAccentColor :

var accentColor = ((System.Windows.Media.Color)Application.Current.Resources["PhoneAccentColor"]);

Hélas ce n’est pas tout, car grâce à ce code, vous obtiendrez un objet Color qui n’est pas de type XNA. Il va donc falloir le convertir.

var xnaColor = new Color { A = accentColor.A, R = accentColor.R, G = accentColor.G, B = accentColor.B };

Une fois le tout assemblé en une fonction GetAccentColor(), vous devriez obtenir ceci :

        public static Color GetAccentColor()
        {
            var accentColor = ((System.Windows.Media.Color)Application.Current.Resources["PhoneAccentColor"]);
            var xnaColor = new Color { A = accentColor.A, R = accentColor.R, G = accentColor.G, B = accentColor.B };

            return xnaColor;
        }

Pour les couleurs inverses et couleurs complémentaires, c’est la même chose :

        public static Color GetAccentComplementatyColor()
        {
            var accentColor = ((System.Windows.Media.Color)Application.Current.Resources["PhoneAccentColor"]);

            byte maxValue = Math.Max(accentColor.R, accentColor.G);
            maxValue = Math.Max(maxValue, accentColor.B);

            byte minValue = Math.Min(accentColor.R, accentColor.G);
            minValue = Math.Min(minValue, accentColor.B);

            var sumValues = (byte)(maxValue + minValue);

            var complementaryColor = new Color
            {
                R = (byte)(sumValues - accentColor.R),
                G = (byte)(sumValues - accentColor.G),
                B = (byte)(sumValues - accentColor.B),
                A = 255
            };

            var xnaColor = new Color
            {
                A = complementaryColor.A,
                R = complementaryColor.R,
                G = complementaryColor.G,
                B = complementaryColor.B
            };

            return xnaColor;
        }

        public static Color GetAccentContrastColor()
        {
            var accentColor = ((System.Windows.Media.Color)Application.Current.Resources["PhoneAccentColor"]);

            var contrastColor = new Color
            {
                R = (byte)(255 - accentColor.R),
                G = (byte)(255 - accentColor.G),
                B = (byte)(255 - accentColor.B),
                A = 255
            };

            var xnaColor = new Color { A = contrastColor.A, R = contrastColor.R, G = contrastColor.G, B = contrastColor.B };

            return xnaColor;
        }

Voici un petit exemple de ce que vous pouvez obtenir avec de gauche à droite du purple, du teal et du pink et leurs couleurs complémentaires (en bas) et opposées (en haut à gauche)

Exemple d'application XNA

Icone

A vous de jouer

Vous n’êtes maintenant plus limités à une seule couleur. Faites en bon usage et rendez vos applications moins austères.

Sources des projets SL et XNA : télécharger

5 commentaires sur “Tutoriel WP7 : Accent Color et dérivées”

  1. rudyhuyn dit :

    Quelques notes :

    Color accentColor = ((SolidColorBrush)Application.Current.Resources[« PhoneAccentColor »];
    ==>Attention, il faut que tu cast en Color et non en SolidColorBrush

    Color accentColor = ((SolidColorBrush)Application.Current.Resources[« PhoneAccentBrush »]).Color;
    ===> optimise
    Color accentColor = ((Color)Application.Current.Resources[« PhoneAccentColor »]);

    Sinon n’hésites pas à contruire les brush associés à tes couleurs complémentaires, ca évitera d’en recréer une (implicitement ou explicitement) à chaque Fill, Background, etc.. 😉

  2. Ldoppea dit :

    Ok pour l’optimisation, j’ai modifié l’article en conséquence. D’ailleurs j’utilisais déjà ce code dans d’autres parties de l’article, mais sans vraiment comprendre 😉

    « Sinon n’hésites pas à contruire les brush associés à tes couleurs complémentaires, ca évitera d’en recréer une à chaque Fill »
    Il me semble que c’est déjà le cas en rajoutant ces couleurs aux ressources depuis le App.xaml.cs, non?

  3. rudyhuyn dit :

    Non, en fait tu as une conversion implicite Color -> SolidColorBrush a chaque fois que tu l’utilises pour un background/fill/foreground, etc… et donc une allocation a chaque fois, en déclarant tes Brush en plus de tes color dans le app.xaml, tu peux directement les référencer et donc gagner très legerement en perf

  4. Julien dit :

    Ce que rudy dis c’est :<
    <rectangle Fill="{StaticResource AccentComplementaryBrush}" Height="100"></rectangle> // BIEN

    <rectangle Fill="{StaticResource AccentComplementaryColor}" Height="100"></rectangle> // PAS BIEN car Binder un color sur un brush ca marche pas

    <rectangle Height="100">
    <rectangle.Fill>
    <SolidColorBrush Color="{StaticResource AccentComplementaryColor}" />
    </rectangle.Fill>
    </rectangle> // BIEN MAIS on construit le Brush a chaque fois donc moins bien que le 1er

    Donc suivant les cas on a besoin soit du brush soit du color donc il faut ajouter les 2 dans les ressources et utiliser selon les besoins !

    Voila j’espere que c’est plus clair :p

  5. Ldoppea dit :

    Ok je comprend mieux le problème.

    Merci à vous deux pour ces explications très utiles!

Laisser une réponse