解决在Windows Phone中的WebBrowser控件中的zoom和ScrollViewer滑动冲突(译)

解决在Windows Phone中的WebBrowser控件中的zoom和ScrollViewer的滑动冲突


这篇博文主要是描述了一个解决在Windows Phone中的WebBrowser控件中的zoom和ScrollViewer滑动冲突的helper类。


Windows Phone 7应用的开发者可以通过使用Webbrowser控件使用在IE9中的拥有的所有功能。该空间允许开发者在程序中呈现本地或者远程的HTML和JavaScript内容。你会发现这个控件比较多的应用与RSS阅读器,这些网页内容可以在程序中良好的呈现而不用再去启动IE浏览器(PS:在Windows Phone中启动IE是要利用启动器的)。WebBrowser也可以用于基于HTML5的应用程序,例如: Property Finder, the PhoneGap-based application I developed recently


现在我们在使用WebBrowser时,常常碰到的一个问题是:怎么样去处理好manipulation事件。

举个例子,在开发过程中遇到了这样一种情况:在Pivot控件里放了一个WebBrowser控件,怎么样去判断和处理横向的滑动手势是要根据Pivot做切换还是用根据WebBrowser做页面内容的移动呢?


在HTML5应用程序中,你可以通过对元数据viewport的设置来对浏览器的评议和缩放做一些控制,例如以下代码就是禁止浏览器的滑动行为:

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


通过添加上面的meta-tag到HTML页面虽然可以禁止用户使用Pinch手势时页面进行缩放,当时不管怎么说都是一个很完美的解决方法。因为用户还是能缩放页面,只不过是当他们释放手指时,又还原到原来的尺寸罢了。

解决方法

我最初以为暂时应该是没有办法去控制WebBrowser控件的行为,它毕竟是围绕着本地控制被.Net包裹着。但是我偶让发现quetzalcoatl 在StackOverflow上的一些回答,quetzalcotl对WebBrowser包裹的.Net层进行了深入的挖掘,发现了一个有趣的控件---PanZoomContainer。


如果你检查过WebBrowser的可视化树,你会发现下面的结构:

\-WebBrowser
  \-Border
    \-Border
      \-PanZoomContainer
        \-Grid
          \-Border (*)
            \-ContentPresenter
              \-TileHost

(可视化转换同样是用了Colin Eberhardt写的一个非常有用的工具-Linq to VisualTree )


这棵可视化树的结构很简单,由一些Grid和Border组成。此中最重要的要属TileHost,他是本地IE9的组件(当然PanZoomContainer也是)。实际上TileHost比不处理手势触发的事件,而是由PanZoomContainer处理的。PanZoomContainer把这些事件转换成手势(如:缩放),并把结果返回给TileHost。


这就意味着我们可以阻止manipulation事件继续传递到PanZoomContainer,并在它们转换为手势前取消它们。

这个Utility类主要是处理这些事件链接到Border上。由于这些事件就被取消了,当事件接收各种的判断条件时通过这些条件可以判断出平移和滑动。


这个类的源码贴在这里:

using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using LinqToVisualTree;
using Microsoft.Phone.Controls;
 
/// <summary>
/// Suppresses pinch zoom and optionally scrolling of the WebBrowser control
/// </summary>
public class WebBrowserHelper
{
  private WebBrowser _browser;
 
  /// <summary>
  /// Gets or sets whether to suppress the scrolling of
  /// the WebBrowser control;
  /// </summary>
  public bool ScrollDisabled { get; set; }
 
  public WebBrowserHelper(WebBrowser browser)
  {
    _browser = browser;
    browser.Loaded += new RoutedEventHandler(browser_Loaded);
  }
 
  private void browser_Loaded(object sender, RoutedEventArgs e)
  {
    var border = _browser.Descendants<Border>().Last() as Border;
 
    border.ManipulationDelta += Border_ManipulationDelta;
    border.ManipulationCompleted += Border_ManipulationCompleted;
  }
 
  private void Border_ManipulationCompleted(object sender,
                                            ManipulationCompletedEventArgs e)
  {
    // suppress zoom
    if (e.FinalVelocities.ExpansionVelocity.X != 0.0 ||
        e.FinalVelocities.ExpansionVelocity.Y != 0.0)
      e.Handled = true;
  }
 
  private void Border_ManipulationDelta(object sender,
                                        ManipulationDeltaEventArgs e)
  {
    // suppress zoom
    if (e.DeltaManipulation.Scale.X != 0.0 ||
        e.DeltaManipulation.Scale.Y != 0.0)
      e.Handled = true;
 
    // optionally suppress scrolling
    if (ScrollDisabled)
    {
      if (e.DeltaManipulation.Translation.X != 0.0 ||
        e.DeltaManipulation.Translation.Y != 0.0)
        e.Handled = true;
    }
  }
}

在属性范围内查找,在我的HTML5应用程序中,当用户从一个页面跳转到下一个页面时,JavaScript代码可以设置通过设置上述helper类的ScrollDisabled属性,从而通知Silverlight容器是否当前界面启用了滑动。


我希望这个简单的Utility类对大家能有帮助,只需要复制这段代码到你的应用程序中就行了。Note,这里使用到了Linq to VisualTree浏览WebBrowser的可视化树,因此你也需要到这里去了解Linq to VisualTree的相关信息。


原文作者:November 17th, 2011 by Colin Eberhardt

原文地址:Suppressing Zoom and Scroll interactions in the Windows Phone 7 WebBrowser Control

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