【问题标题】:Windows Phone 8.1 - Handle WebView vertical scroll by outer ScrollViewer elementWindows Phone 8.1 - 通过外部 ScrollViewer 元素处理 WebView 垂直滚动
【发布时间】:2015-08-22 17:01:26
【问题描述】:

问题

我必须在 Windows Phone 8.1 应用程序的 ScrollViewer 中显示 WebView,并满足以下要求:

  1. WebView 高度应根据其内容进行调整。
  2. WebView 垂直滚动应由外部 ScrollViewer 处理。
  3. WebView 应该处理水平滚动、缩放(捏缩放)、文本选择(使用默认复制按钮)和链接导航。

下图是我的模拟布局(左侧)和类似功能的最佳示例 - 内置邮件应用程序(右侧)

XAML 布局示例:

<ScrollViewer>
    <Grid Margin="12">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <TextBlock Text="My content" />
        </Grid>
        <WebView Grid.Row="1" x:Name="WebViewComponent"></WebView>
    </Grid>
</ScrollViewer>

我做了什么

Measure HTML content and adjusting the WebView height - 这部分工作,经过多次调整,我能够为WebView 元素设置正确的高度。

Subscribing to a Border element inside a WebView - 没用。这里的问题是,在 Windows Phone 8.1 中,WebView 组件似乎没有可视子组件(至少没有 DependencyObject's)

我也尝试过使用ManupulationModeIsHitTestVisible 属性,但没有成功

更新 为所需的WebView 功能添加了文本选择和复制按钮。在原始问题内容中不知何故错过了它。

【问题讨论】:

  • 只是出于好奇,您是否尝试过注入一些 css 来禁用溢出:滚动,以便您的滚动查看器实际上可以完成它的工作。像this 这样的东西?我希望我现在有更多的空闲时间去玩它,无论如何这似乎是一个普遍的问题。
  • @Chris 我做到了。 WebView 完全捕获指针交互并与“压缩”滚动之类的东西做出反应(不太确定这是否是一个恰当的术语 - 滚动速度非常慢,一旦松开手指就会恢复)。
  • 类似“一个滚动滚动所有”的问题:)

标签: c# xaml webview windows-phone windows-phone-8.1


【解决方案1】:

您是否尝试将 WebView 的 Height 属性设置为 Auto?

<ScrollViewer x:Name="scrollViewer" >
    <Grid Margin="12">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock Text="My content" />
        <Grid Background="Transparent"
              Margin="0"
              Grid.Row="1">
            <WebView ScrollViewer.ZoomMode="Enabled"
                     x:Name="WebViewComponent"  
                     Margin="0" 
                     Height="Auto" />
        </Grid>
    </Grid>
</ScrollViewer>

【讨论】:

  • 我相信 Auto 是 WebView.Height 属性的默认值,尽管现在我做到了。完全没有效果。 ScrollViewer.ZoomMode="Enabled" 也不会影响内部浏览器滚动。
【解决方案2】:

我检查了它并尝试了一些东西,但无法让它按照你想要的方式工作。想出不同的设计可能更容易。基本上,不包括外部ScrollViewer

  • 一个选项(可能有点hacky,没有测试过)是通过一些JS将你的内容注入页面,并且只使用WebView

  • 如果您的内容很小,您可以将其留在页面顶部,删除ScrollViewer 并让WebView 处理所有内容。 WebView 会更小,但可以正常工作。

这些只是不同设计的一些示例。如果你告诉我为什么它们不起作用,或者如果你给我更多关于你的实际问题的信息,我可能会想出更合适的东西。

【讨论】:

  • 问题是屏幕顶部显示的内容可能很复杂,包含图像、按钮等。抱歉,我似乎以某种方式错过了原始问题帖子中的那部分。我意识到可以将所有内容都包含在WebView 中,但这需要付出很大的努力。无论如何感谢您的建议
  • @danyloid 是的,复杂的内容使它...复杂:) 还有两个想法:1)使用 Pivot,一个页面上的内容,另一个页面上的 webview; 2) 像垂直轴这样的东西——你会在底部看到 webview,一旦你点击它,它就会几乎全屏显示,顶部只有一个小东西,你可以从中返回到其他内容。
  • 谢谢,我没有考虑过第二种方法。这可能不是最佳解决方案,但值得考虑。
【解决方案3】:

我一直面临这个问题,我得到了部分解决方法(不包括文本选择)。

基本上为了能够使用包含webview的scrollviewer,你需要拖动一些东西,所以我使用了一个与webview高度和宽度相同的矩形。

<ScrollViewer Name="ScrollViewer">
    <Grid x:Name="LayoutRoot" Height="Auto">
        <Grid.RowDefinitions>
            <RowDefinition Height="200"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid Name="GridHeader">
            <Image Stretch="UniformToFill" Source="ms-appx:///Assets/img_default_header.jpg" />
         </Grid>                
        <Grid Grid.Row="1" x:Name="GridNews" Margin="12,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <WebView Margin="-6,12,0,-6" Grid.Row="0" x:Name="WebviewContent" VerticalAlignment="Top" DefaultBackgroundColor="Transparent" /> 
            <Rectangle Margin="0,12,0,0" Height="{Binding Height, ElementName=WebviewContent}" Name="RecWeb" VerticalAlignment="Top" Fill ="#00000000" Tapped="RecWeb_Tapped" />
        </Grid>
        <Grid Name="GridRelatedNews" Grid.Row="2" Margin="12,0">
            <ListView ItemsSource="{Binding NewsDetail.RelatedStory}" ScrollViewer.VerticalScrollBarVisibility="Hidden">  
            </ListView>
        </Grid>
 </ScrollViewer>

现在我们需要注入一些 css 和 javascript 以使 webview 高度适应内容(我在另一个 stackoverflow 线程上找到了一些代码示例,忘记跟踪它的来源)

string htmlFragment = @"
                                    <html>
                                        <head>
                                        <meta name=""viewport"" content=""width="+width+@", initial-scale=1, user-scalable=no"" />
                                            <script type=""text/javascript"">
                                                function loadLink(x,y){
                                                window.external.notify('x='+x+'y='+y);
                                                var el = document.elementFromPoint(x, y);
                                                el.click();};                                                   
                                            </script>
                                        <style>
                                        " + CSS + @"
                                        </style>
                                        </head>
                                        <body onLoad=""window.external.notify('rendered_height='+document.getElementById('content').offsetHeight);"">
                                            <div id='content' style=""font-size:16px; color:#222222;"">" + original +
                                          @"</div>
                                        </body>
                                    </html>";

然后添加webview webscript通知事件来确定webview(和矩形)的渲染高度:

void WebviewContent_ScriptNotify(object sender, NotifyEventArgs e)
{
    if (e.Value.Contains("rendered_height"))
    {
        if (valuePair != null && valuePair[0] == "rendered_height")
        {
            double renderedHeight = double.Parse(valuePair[1]);                 
            WebviewContent.Height = renderedHeight;

        }
    }
 }

我设法允许此解决方案能够使用此方法(loadLink javascript 方法)单击内容中的某些链接:

private async void RecWeb_Tapped(object sender, TappedRoutedEventArgs e)
    {
        Point p = e.GetPosition(WebviewContent);
        int x = Convert.ToInt32(p.X);
        int y = Convert.ToInt32(p.Y);
        string[] size = { x.ToString(), y.ToString() };
        await WebviewContent.InvokeScriptAsync("loadLink",size);
    }

也许您可以从那里为您的选择文本问题添加一个事件处理程序。使用此解决方案的要点也是在 javascript 中找到等效的事件处理程序。

【讨论】:

  • 谢谢。我想这是最接近的。
  • 这里是@tdmanutd的解决方案gist.github.com/Ouadie/78fc85965ebaf49e06d4的完整实现@
  • 我也面临同样的问题。我会试试这个解决方案。感谢您发布..
  • @Ouadie LoadLink 功能对我不起作用。链接没有被点击。你有什么想法吗?
  • @LovetoCode 首先你必须检查你是否正确调用了await this.WebviewContent.InvokeScriptAsync("loadLink", size);,然后在javascript中检查alertconsole.log你是否正确收到了loadLink的调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多