Hide/Show "Scroll To Top" 基于WebView滚动的按钮

Hide/Show "Scroll To Top" button based on WebView's scroll

我正在制作一个包含 WebView 的 UWP 应用程序,我想实现一个简单的 "Scroll to top" 按钮,我已经在这个按钮后面编写了代码并且它可以工作:

        private async void ToTopButton_Click(object sender, RoutedEventArgs e)
        {
        var ScrollToTopString = @"var int = setInterval(function() { 
        window.scrollBy(0, -36);

        if( window.pageYOffset === 0 )
            clearInterval(int);
        }, 0.1);";
        await MyWebView.InvokeScriptAsync("eval", new string[] { ScrollToTopString });
        }

但现在我只想在用户需要时显示该按钮,因此如果 WebView 滚动条位于顶部,则该按钮应该被隐藏,反之亦然...我已经研究过,但我还没有找到任何东西。谁能帮帮我吗?谢谢

I want to only show the button if the user need it, so if the WebView scroll is on top the button should be hidden and viceversa.

应用程序无法直接访问 WebView 的滚动条,因为它是嵌入式 Edge 浏览器视图的一部分。因此,您可能需要使用脚本来监视 onscroll event 的滚动操作,并通过 InvokeScriptAsync.

调用脚本

然后如果滚动条在顶部,您可能需要通知您的 uwp 应用程序。为此,您可能需要使用 WebviewScriptNotify 事件。当托管 HTML 页面调用 window.external.notify 并传递字符串参数时,它可以在您的 Windows 商店应用中触发 ScriptNotify 事件。

但要注意ScriptNotify的注释:

To prevent malicious scripts from exploiting this event, be sure to enable it only for trusted URIs.

您必须在应用清单的 ApplicationContentUriRules 部分中包含页面的 URI。 (您可以在 Package.appxmanifest 设计器的内容 URI 选项卡上的 Visual Studio 中执行此操作。)此列表中的 URI 必须使用 HTTPS,并且可以包含子域通配符(例如,“https://.microsoft.com"), but they can't contain domain wildcards (for example, "https://.com”和 "https://.").

这是完成的示例:

<Button x:Name="ToTopButton" Content="to top" Click="ToTopButton_Click"></Button>
<WebView x:Name="MyWebView"  Height="500" Width="400" Source="https://www.microsoft.com/en-sg/"  ScriptNotify="MyWebView_ScriptNotify" NavigationCompleted="MyWebView_NavigationCompleted"></WebView>

代码隐藏

private async void ToTopButton_Click(object sender, RoutedEventArgs e)
{
    var ScrollToTopString = @"var int = setInterval(function(){window.scrollBy(0, -36); if( window.pageYOffset === 0 ) clearInterval(int); }, 0.1);";
    await MyWebView.InvokeScriptAsync("eval", new string[] { ScrollToTopString });
}

private void MyWebView_ScriptNotify(object sender, NotifyEventArgs e)
{      
    var result = e.Value;
    if (result == "true")
    {
        ToTopButton.Visibility = Visibility.Collapsed;
    }
    else
    {
        ToTopButton.Visibility = Visibility.Visible;
    }
} 

private async void MyWebView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
    string addlistener = @"window.onscroll = function() {myFunction()};
                          function myFunction()
                          {if( window.pageYOffset === 0 )  window.external.notify('true'); else window.external.notify('false');} "; 
    await MyWebView.InvokeScriptAsync("eval", new string[] { addlistener });
    //first time check
    var firstnotify = "if( window.pageYOffset === 0 )  window.external.notify('true'); else window.external.notify('false')";
    await MyWebView.InvokeScriptAsync("eval", new string[] { firstnotify });
}

频繁通知可能会影响性能,除非您必须使用该功能,否则不推荐这样做。