Afficher proprement du HTML dans une application Windows Phone
Par Guillaume Lacasa, posté le 26/08/2011
Profil : Développeur | Niveau : Intermédiaire (200)
--
Mise à jour (20/02/2012) : Une fois que vous aurez fini de lire cet article, je vous invite à compléter votre contrôle HTML en lisant cet article de Pierre Cauchois, qui propose en plus de supprimer les manipulations http://blogs.msdn.com/b/pierreca/archive/2012/02/20/windows-phone-7-5-supprimer-le-pinch-to-zoom-sur-un-contr-244-le-webbrowser.aspx
--
Il arrive souvent qu'on ait besoin d'afficher du contenu HTML dans une application Windows Phone. Si le contrôle WebBrowser permets d'afficher facilement du contenu HTML, nous allons voir qu'il existe quelques subtilités à connaitre pour intégrer correctement ce contenu HTML au design de notre application.
Pour cet article, nous allons prendre l'exemple d'une application qui garde le standard Metro pour son design (donc qui utilise les couleurs de fond et d'accentuation définies par l'utilisateur sur son téléphone).
Vous pouvez télécharger le code source complet de cet article.
Affichage du HTML
Pour commencer, nous allons donc faire un contrôle qui va afficher du HTML. Rien de plus simple, nous avons un contrôle WebBrowser, et une méthode NavigateToString qui fait exactement ça.
HtmlControl.xaml :
<Grid x:Class="DisplayHtmlInPhone.HtmlControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:Controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" mc:Ignorable="d" d:DesignHeight="480" d:DesignWidth="480"> <Controls:WebBrowser x:Name="browser" /> Grid>HtmlControl.xaml.cs :
namespace DisplayHtmlInPhone { public partial class HtmlControl { public HtmlControl() { InitializeComponent(); } public void DisplayHtml(String html) { browser.NavigateToString(html); } } }Si on essaye déjà d'utiliser ce contrôle, on risque d'avoir l'erreur suivante, si on essaye d'afficher du html avant que le WebBrowser n'ait fini de se charger :
Nous allons donc modifier notre code, pour que l'affichage du html ne se fasse qu'une fois le contrôle chargé, quel que soit le moment de l'appel de notre fonction DisplayHtml ; en se branchant sur l'évènement Loaded.
private bool _isBrowserLoaded = false; private string _htmlToLoad; public void DisplayHtml(String html) { if (_isBrowserLoaded) { browser.NavigateToString(html); } else _htmlToLoad = html; } private void browser_Loaded(object sender, RoutedEventArgs e) { _isBrowserLoaded = true; if (!String.IsNullOrEmpty(_htmlToLoad)) DisplayHtml(_htmlToLoad); }On peut maintenant tester notre application pour afficher du code HTML :
Amélioration de l'affichage
Comme on peut le voir, le HTML s'affiche. Mais pas comme nous le souhaitions : les longues phrases peuvent dépasser sur le coté selon le niveau de zoom, et les images sont trop petites pour êtres lisibles. On peut arranger ça à l'aide de balises à ajouter dans l'en-tête du code HTML.
Afin de pouvoir les ajouter, on va créer un template dans lequel on injectera ensuite le code html qu'on veut afficher. On crée donc dans notre projet un fichier template.html, et dans ses propriétés, on mets "Build Action" sur "Resource". On y mets le contenu suivant :
<html> <head> <meta name="viewport" content="width=device-width" /> <meta name="viewport" content="user-scalable=no" /> head> <body> {0} body> html>On met à jour la fonction d'affichage du html pour se baser sur le template :
public void DisplayHtml(String html) { if (_isBrowserLoaded) { // On charge le template StreamResourceInfo sri = Application.GetResourceStream(new Uri("DisplayHtmlInPhone;component/template.html", UriKind.Relative)); using (StreamReader templateStream = new StreamReader(sri.Stream)) { String template = templateStream.ReadToEnd(); // On y insère le code html String htmlToshow = String.Format(template, html, FetchBackgroundColor(), FetchFontColor(), FetchAccentColor()); browser.NavigateToString(htmlToshow); } } else _htmlToLoad = html; }Ceci nous permet de limiter la largeur de la page, et bloque le zoom. Nous avons donc un affichage plus cohérent : texte et images sont directement adaptés à la taille de l'écran.
Gestion des couleurs
On a réussi à afficher du html, mais on se retrouve avec un texte noir sur fond blanc, ce qui contraste un peu avec le look du téléphone, si l'utilisateur a décidé d'utiliser un thème sombre.
Pour rappel, Windows Phone permets de choisir un thème sombre (texte blanc sur fond noir) ou clair (texte noir sur fond blanc), et de choisir une couleur d'accentuation (couleur utilisée dans tout le système pour mettre en valeur certains éléments). Le thème peut être repris dans les applications, et nous allons voir comment l'utiliser dans notre page html.
Première chose à faire, connaitre les couleurs : on peut les connaitre à l'aide des ressources ayant la clé "PhoneBackgroundColor" pour le fond d'écran, et "PhoneAccentColor" pour la couleur d'accentuation.
private bool IsBackgroundBlack() { Color mc = (Color)Resources["PhoneBackgroundColor"]; return mc == Colors.Black; } private string FetchBackgroundColor() { // On retourne le code hexadecimal de la couleur de fond return IsBackgroundBlack() ? "#000" : "#fff"; } private string FetchFontColor() { // Si le fond est noir, le texte est blanc, et vice-versa return IsBackgroundBlack() ? "#fff" : "#000"; }Si pour la couleur de fond nous n'avons que 2 possibilités (noir ou blanc), ce n'est pas le cas de la couleur d'accentuation ou nous avons une liste de couleur indéterminée (n'oublions pas que les constructeurs et opérateurs peuvent ajouter leur propre couleur) ; nous ne pouvons donc pas nous baser sur une liste existante, on va donc cette fois recréer le code hexadécimal à partir de la couleur récupérée.
private string FetchAccentColor() { Color c = (Color)Resources["PhoneAccentColor"]; return String.Concat("#", c.R.ToString("X2"), c.G.ToString("X2"), c.B.ToString("X2")); }Maintenant que nous connaissons les couleurs, il va nous falloir les appliquer à notre page html. On ne peut pas mettre de fond transparent au WebBrowser, nous sommes donc obligés d'envoyer ces couleurs au style de la page. Nous revenons donc à notre template html pour y ajouter des styles:
(Les accolades dans les styles sont doublées pour pouvoir utiliser la fonction String.Format())<html> <head> <meta name="viewport" content="width=device-width" /> <meta name="viewport" content="user-scalable=no" /> <style type="text/css"> body {{ width: 100%; color: {2}; background-color: {1}; }} a {{ color: {3}; }} style> head> <body> {0} body> html>Il ne reste plus qu'à modifier le DisplayHtml pour passer les couleurs en paramètre:
// On y insère le code html String htmlToshow = String.Format(template, html, FetchBackgroundColor(), FetchFontColor(), FetchAccentColor());Ce qui nous donne le résultat suivant :
Gestion des liens
Depuis le début de cet article, je n'ai fait que détourner le WebBrowser pour en faire un "simple" contrôle d'affichage de html. C'est à dire que je veux une zone d'affichage dans mon application, et certainement pas un navigateur : nous allons donc devoir désactiver les liens, pour être sûr de ne pas retrouver Facebook au milieu de notre application, et renvoyer sur le vrai navigateur du téléphone.
On peut faire ça sur l'évènement "Navigating" du WebBrowser :
<Controls:WebBrowser x:Name="browser" Loaded="browser_Loaded" Navigating="browser_Navigating"/>private void browser_Navigating(object sender, Microsoft.Phone.Controls.NavigatingEventArgs e) { // On annule la navigation e.Cancel = true; // On envoie le lien dans IE WebBrowserTask ie = new WebBrowserTask(); ie.URL = e.Uri.ToString(); ie.Show(); }L'utilisateur pourra ensuite utiliser le bouton back pour revenir à l'application et son contenu original.
Conclusion
Nous avons donc réussi à créer un contrôle simple pour afficher directement du contenu html, capable de s'intégrer correctement dans votre application.
Vous pouvez télécharger le code source complet de cet article pour le tester et l'adapter à vos besoins.
Passionné par les technologies web depuis sa plus tendre enfance, il fait ses premières armes en PHP avant de se tourner vers ASP .NET Webforms, MVC, et Javascript. Lorsqu'il s'éloigne de son ordinateur, c'est pour aller trouver refuge dans sa collection de bandes dessinées.



