首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Windows 8 Store Apps 開發實戰(8):WebView 控件 — 基礎導航、JavaScript 互通、Share Contract 分享與全螢幕處理

     編輯:關於.NET

前言

WebView 是 WinRT 內嵌瀏覽器控件,支援完整 HTML5/CSS3/JavaScript。但它是 獨立視窗層級 的原生控件,不允許任何 XAML 元素覆蓋其上方(Z-index 無效),這帶來全螢幕、AppBar 遮擋等特殊挑戰。本文涵蓋基礎導航、JS 雙向互通、Share Contract 分享、全螢幕模式下的 AppBar 共存技巧。

一、基礎導航與內容載入

核心 API

  • Source / Navigate(Uri):導航到 URL
  • NavigateToString(string html):直接解析 HTML 字串
  • LoadCompleted:DOM 載入完成事件
  • NavigationFailed:導航失敗事件(WebViewNavigationFailedEventArgs.WebErrorStatus)

範例

<StackPanel Margin="120 0 0 0">
    <Button x:Name="btnNavigateUrl" Content="導航到指定 URL" Click="btnNavigateUrl_Click"/>
    <Button x:Name="btnShowHtml" Content="解析 HTML 字串" Click="btnShowHtml_Click" Margin="0 10 0 0"/>
    <Button x:Name="btnFullScreen" Content="全螢幕 WebView 測試" Click="btnFullScreen_Click" Margin="0 10 0 0"/>
    <WebView x:Name="webView" Width="400" Height="300" HorizontalAlignment="Left" Margin="0 10 0 0"/>
</StackPanel>
private void btnNavigateUrl_Click(object sender, RoutedEventArgs e)
{
    webView.Navigate(new Uri("https://webabcd.cnblogs.com/", UriKind.Absolute));
    webView.NavigationFailed += webView_NavigationFailed;
}

async void webView_NavigationFailed(object sender, WebViewNavigationFailedEventArgs e)
{
    await new MessageDialog(e.WebErrorStatus.ToString()).ShowAsync();
}

private void btnShowHtml_Click(object sender, RoutedEventArgs e)
{
    webView.NavigateToString("I am webabcd");
}

private void btnFullScreen_Click(object sender, RoutedEventArgs e)
{
    var root = Window.Current.Content as Frame;
    root.Navigate(typeof(FullScreen));
}

二、App 與 JavaScript 雙向互通

App → JS:InvokeScript

  • webView.InvokeScript("functionName", string[] args):呼叫 JS 函數並取得回傳值(字串)
  • 特殊函數 "eval":執行任意 JS 表達式(如 document.title)

JS → App:ScriptNotify

  • JS 呼叫 window.external.notify('message')
  • App 監聽 webView.ScriptNotify 事件,NotifyEventArgs.Value 取得訊息
  • 安全限制:必須先設定 webView.AllowedScriptNotifyUris 允許的來源 URI 列表

完整範例

<StackPanel Margin="120 0 0 0">
    <Button x:Name="btnInvokeJS" Content="App 呼叫 WebView JS" Click="btnInvokeJS_Click"/>
    <Button x:Name="btnAccessDOM" Content="透過 eval 存取 DOM" Click="btnAccessDOM_Click" Margin="0 10 0 0"/>
    <WebView x:Name="webView" Width="400" Height="300"
             Source="https://localhost:39629/WebViewInteract.html"
             HorizontalAlignment="Left" Margin="0 10 0 0"/>
</StackPanel>
public sealed partial class Interact : Page
{
    public Interact()
    {
        this.InitializeComponent();
        // 必須設定允許 ScriptNotify 的 URI
        var allowedUris = new List<Uri> { new Uri("https://localhost:39629/") };
        webView.AllowedScriptNotifyUris = allowedUris;
        webView.ScriptNotify += webView_ScriptNotify;
    }

    async void webView_ScriptNotify(object sender, NotifyEventArgs e)
    {
        await new MessageDialog(e.Value).ShowAsync(); // 顯示 JS 傳來的訊息
    }

    private async void btnInvokeJS_Click(object sender, RoutedEventArgs e)
    {
        // 呼叫 JS: sayHelloToJs('webabcd')
        string result = webView.InvokeScript("sayHelloToJs", new[] { "webabcd" });
        await new MessageDialog(result).ShowAsync();
    }

    private async void btnAccessDOM_Click(object sender, RoutedEventArgs e)
    {
        // eval 取得 document.title
        string result = webView.InvokeScript("eval", new[] { "document.title" });
        await new MessageDialog(result).ShowAsync();
    }
}

配合的 HTML (WebViewInteract.html)

<script>
    function sayHelloToJs(name) {
        return "Hello " + name + " from JS!";
    }
    // 主動通知 App
    window.external.notify("JS 主動送訊息給 App");
</script>

三、Share Contract 分享 WebView 選取內容

WebView.DataTransferPackage 回傳 DataPackage,包含使用者選取的文字/圖片/HTML/連結等格式。

範例

<StackPanel Margin="120 0 0 0">
    <Button x:Name="btnShare" Content="分享 WebView 選取文字" Click="btnShare_Click"/>
    <WebView x:Name="webView" Width="400" Height="300"
             Source="https://webabcd.cnblogs.com/"
             HorizontalAlignment="Left" Margin="0 10 0 0"/>
</StackPanel>
public sealed partial class Share : Page
{
    private DataTransferManager _dtm;

    private void btnShare_Click(object sender, RoutedEventArgs e)
    {
        _dtm = DataTransferManager.GetForCurrentView();
        _dtm.DataRequested += _dtm_DataRequested;
        DataTransferManager.ShowShareUI();
    }

    void _dtm_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
    {
        var pkg = webView.DataTransferPackage;
        var view = pkg.GetView();

        if (view.Contains(StandardDataFormats.Text))
        {
            pkg.Properties.Title = "Title";
            pkg.Properties.Description = "Description";
            args.Request.Data = pkg;
        }
        else
        {
            args.Request.FailWithDisplayText("沒有選中任何內容");
        }
        _dtm.DataRequested -= _dtm_DataRequested;
    }
}

四、全螢幕 WebView 與 AppBar 共存難題與解法

問題:WebView 全螢幕時會遮擋所有 XAML 元素,包含 AppBar。
解法:AppBar.Opened 時縮減 WebView 高度並向上位移,AppBar.Closed 時恢復,並配合動畫平滑過渡。

XAML:BottomAppBar + WebView RenderTransform

<Page.BottomAppBar>
    <AppBar x:Name="appBar">
        <StackPanel Orientation="Horizontal">
            <Button x:Name="btnHome" Style="{StaticResource HomeAppBarButtonStyle}" Click="btnHome_Click"/>
        </StackPanel>
    </AppBar>
</Page.BottomAppBar>

<Grid Background="Transparent">
    <WebView x:Name="webView" Source="https://webabcd.cnblogs.com/">
        <WebView.RenderTransform>
            <CompositeTransform/>
        </WebView.RenderTransform>
    </WebView>
</Grid>

動畫資源

<Page.Resources>
    <Storyboard x:Name="sbOpenAppBar">
        <DoubleAnimation x:Name="aniTranslateYOpen"
                         Storyboard.TargetName="webView"
                         Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
                         Duration="0:0:0.367">
            <DoubleAnimation.EasingFunction>
                <ExponentialEase EasingMode="EaseOut"/>
            </DoubleAnimation.EasingFunction>
        </DoubleAnimation>
    </Storyboard>
    <Storyboard x:Name="sbCloseAppBar">
        <DoubleAnimation x:Name="aniTranslateYClose"
                         Storyboard.TargetName="webView"
                         Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
                         Duration="0:0:0.367">
            <DoubleAnimation.EasingFunction>
                <ExponentialEase EasingMode="EaseOut"/>
            </DoubleAnimation.EasingFunction>
        </DoubleAnimation>
    </Storyboard>
</Page.Resources>

後台邏輯

public sealed partial class FullScreen : Page
{
    public FullScreen() { this.InitializeComponent(); }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        appBar.Opened += appBar_Opened;
        appBar.Closed += appBar_Closed;
    }

    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        appBar.Opened -= appBar_Opened;
        appBar.Closed -= appBar_Closed;
    }

    void appBar_Opened(object sender, object e)
    {
        this.UpdateLayout(); // 強制佈局更新以取得實際高度
        double h = appBar.ActualHeight;
        webView.Height = webView.ActualHeight - h; // 縮減高度
        aniTranslateYOpen.To = -h / 2.0;           // 向上位移一半(置中效果)
        sbOpenAppBar.Begin();
    }

    void appBar_Closed(object sender, object e)
    {
        this.UpdateLayout();
        double h = appBar.ActualHeight;
        webView.Height = webView.ActualHeight + h; // 恢復高度
        aniTranslateYClose.To = h / 2.0;
        sbCloseAppBar.Begin();
    }

    private void btnHome_Click(object sender, RoutedEventArgs e)
    {
        var root = Window.Current.Content as Frame;
        root.Navigate(typeof(MainPage));
    }
}

進階替代方案:WebViewBrush

若需在 WebView 上方疊加 XAML 元素(如浮水印、註解),可使用 WebViewBrush 將 WebView 內容繪製到 Rectangle.Fill,然後隱藏原 WebView。WebViewBrush 上方可自由放置 XAML 元素。

五、小結

  1. 導航:Navigate/NavigateToString、LoadCompleted/NavigationFailed
  2. JS 互通:InvokeScript(App→JS)、ScriptNotify+AllowedScriptNotifyUris(JS→App)、eval 存取 DOM
  3. 分享:WebView.DataTransferPackage + DataTransferManager
  4. 全螢幕:WebView 遮擋一切,利用 AppBar.Opened/Closed 動態調整 WebView 高度與 RenderTransform.TranslateY 實現共存

掌握這些技巧,即可在 App 中無縫整合豐富網頁內容,並解決全螢幕互動難題。


原始碼下載:https://files.cnblogs.com/webabcd/Windows8.rar

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved