在Windows Phone 7 中显示HTML代码(译)

在早期推广宣传推出Windows Phone 7的时候,我们做了大量的工作去帮助客户建立早期的应用程序,移植他们的已经成熟的应用到WP7市场上来。我们提供指导和协助帮助他们设计开发出符合产品设计标准和遵循WP7应用程序认证规范的应用程序。


像开发出来的程序有很多比如Telegraph Media GroupTelegraph Fashion应用程序。他们在开发这个应用的过程中和在我们微软技术研发中心的Martin BeebyDave Brown花了一些时间解决一个特定的一个问题:如何良好的显示HTML内容?


在这个应用中数据主要是来自于包含特定格式的HTML代码的RSS 提要。如果是开发Silverlight应用程序一般的做法是使用WebBrowser控件,并且使用NavigateToString()方法通过传递包含HTML代码的字符串参数显示该内容。


WP7平台上使用这种方式去显示的时候,开发团队一开始就遇到了一些问题:

       1. WebBrowser控件暂时不能改变其背景色。(默认是白色的背景,在加载中可能会更内容的背景颜色不搭调)。

       2. Telegraph想在他们的应用中把WebBrowser控件缩小放大的功能屏蔽掉。


我们同时来看待这些问题。为了使WebBrowser更契合用户选择的主题,使WebBrowser能够改变背景色这个需求是很合理的。在黑背景上的白色Browser是要避免的,反之亦然。当时在解决这个问题的过程中,该团队使用一些检测代码去侦测当前的背景颜色。通过转换成一个颜色16进制的值,然后在CSS中去处理当前页面的背景颜色。


下面是上述方法的代码—我认为或许可以重构成更简单的代码—但是上述方法的整个过程是这样的:在WebBrowser加载过程中,我们先检测当前的字体颜色和背景颜色应该用什么然后设置它们的值最后传递字符串给WebBrowser控件。现在我们忽略脚本—我们来解决第二个问题。

private string FetchBackgroundColor()
{
   return IsBackgroundBlack() ? "#000;" : "#fff";
}
private string FetchFontColor()
{
  return IsBackgroundBlack() ? "#fff;" : "#000";
}
private static bool IsBackgroundBlack()
{
  return FetchBackGroundColor() == "#FF000000";
}
private static string FetchBackGroundColor()
{
  string color;
  Color mc =
    (Color)Application.Current.Resources["PhoneBackgroundColor"];
  color = mc.ToString();
  return color;
}
private void wb1_Loaded(object sender, RoutedEventArgs e)
{
  string fontColor = FetchFontColor();
  string backgroundColor = FetchBackgroundColor();
  SetBackground();
  var html = "<p>Lorem ipsum dolor sit amet, consectetur " + 
    "adipiscing elit. Mauris sit amet dignissim purus. " + 
    "Pellentesque habitant morbi tristique senectus et " +
    "netus et malesuada fames ac turpis egestas. " +
    "Curabitur ante mauris, tempor congue lobortis id, " +
    "gravida nec mi. Sed laoreet neque eget lacus " +
    "vestibulum vel euismod sapien elementum. Maecenas " +
    "malesuada, orci id facilisis volutpat, dui dui " +
    "cursus nulla, luctus congue magna ligula sed urna." +
    "</p>" + 
    "<p>Suspendisse luctus rutrum quam non rutrum. " +
    "Maecenas sed mauris id metus sodales lobortis eu sit " +
    "amet nibh. Lorem ipsum dolor sit amet, consectetur " +
    "adipiscing elit. Donec convallis vehicula lacinia. " +
    "Duis blandit vestibulum tristique. Morbi tincidunt " +
    "lacinia condimentum. Morbi quis ipsum lorem, mollis " +
    "lobortis quam. Curabitur ac lectus justo, non " +
    "placerat sapien. Integer non sem nec elit fermentum " +
    "placerat. Vivamus id metus quam. Aliquam erat " +
    "volutpat. Cras et mauris cursus lectus dignissim " +
    "commodo varius nec ligula.</p>";
  var htmlScript = "<script>function getDocHeight() { " +
    "return document.getElementById('pageWrapper').offsetHeight;" + 
    "}" +
    "function SendDataToPhoneApp() {" +
    "window.external.Notify('' + getDocHeight());" +
    "}</script>";
  var htmlConcat = string.Format("<html><head>{0}</head>" + 
    "<body style=\"margin:0px;padding:0px;background-color:{3};\" " +
    "onLoad=\"SendDataToPhoneApp()\">" +
    "<div id=\"pageWrapper\" style=\"100%; color:{2}; " +
    "background-color:{3}\">{1}</div></body></html>", 
    htmlScript, 
    html, 
    fontColor, 
    backgroundColor);
  webBrowser1.NavigateToString(htmlConcat);
  webBrowser1.IsScriptEnabled = true;
  webBrowser1.ScriptNotify += 
    new EventHandler<NotifyEventArgs>(wb1_ScriptNotify);
}
private void SetBackground()
{
  Color mc =
    (Color)Application.Current.Resources["PhoneBackgroundColor"];
  webBrowser1.Background = new SolidColorBrush(mc);
}

对于第二个问题,最初的方法是设置WebBrowserIsHitTestVisibleFalse。当然这样做会引发另一个问题,那就是由于WebBrowser中被嵌入了一个ScrollViewer,设置IsHitTestVisibleFalse后Scrollviewer的滑动也会被相应的禁用。现在的挑战是要把WebBrowser控件的高度设置为内容的高度。


当时为了解决这个问题考虑了两种方案。第一种就是写一个方法去测量字符串内容的长度,但是这个方案没有被执行。那是因为在需求中数据内容中图片的高度也是须要被测量的。


另一种方案就把字符串数据传递给WebBrowser控件,然后通过运行JavaScript方法去测量内容的高度,回传高度信息给Silverlight。最后设置WebBrowser控件的高度。这就上面JavaScript代码要做的处理。这个ScriptNotify handler中代码大致如下:

private void wb1_ScriptNotify(object sender, NotifyEventArgs e)
{
  // The browser is zooming the text so we need to
  // reduce the pixel size by the zoom level... 
  // Which is about 0.50
  webBrowser1.Height = Convert.ToDouble(e.Value) * 0.50;
}

如果不是处理比较长的内容,这个方法是很管用的。但是当WebBrowser的高度设置为超过1800像素时,程序运行是会直接崩溃掉。最后证明,还有更简单的方法能达到同样的效果。

与设置WebBrowserIsHitTestVisible不同的是,我们可以在HTML代码中设置meta 标签,这样就可以禁用Browser的放大缩小功能。

<meta name="viewport" content="width=320" />
<meta name="viewport" content="user-scalable=no" />

或者

<meta name="viewport" content="width=320,user-scalable=no" />

这里的标签把可视区域设置成320像素(避免水平方向的滑动)同时指定了用户不能在可视区域去缩放可视内容。将这些标签注入到HTML代码中就实现了我们的需求。其实,是很简单的。解决问题的过程就是这样,一步一步,一点一滴,坚持不懈的去思考,问题都是得到比较好的解决的。


希望对你有帮助,欢迎大家讨论。

原文地址:http://blogs.msdn.com/b/mikeormond/archive/2010/12/16/displaying-html-content-in-windows-phone-7.aspx 

原文地址:https://www.cnblogs.com/navigator/p/2917680.html