Xamarin.Forms WebView

Download Sample 下載範例

WebView 是在您的應用程式中顯示 Web 和 HTML 內容的檢視:

In App Browser

Content

WebView 支援下列內容類型:

  • HTML 和 CSS 網站 – WebView 完全支援使用 HTML 和 CSS 撰寫的網站,包括 JavaScript 支援。
  • 檔 – 因為 WebView 是使用每個平臺上的原生元件來實作,因此 WebView 能夠以基礎平台支援的格式顯示檔。
  • HTML 字串 – WebView 可以從記憶體顯示 HTML 字串。
  • 本機檔案 – WebView 可以呈現應用程式內嵌上述任何內容類型。

注意

WebView 在 Windows 上不支援 Silverlight、Flash 或任何 ActiveX 控件,即使 Internet Explorer 支援於該平臺上也一樣。

網站

若要從因特網顯示網站,請將 的 Source 屬性設定WebView為字串 URL:

var browser = new WebView
{
  Source = "https://dotnet.microsoft.com/apps/xamarin"
};

注意

URL 必須以指定的通訊協定完整形成(也就是其前面必須加上 “http://” 或 “https://”。

iOS 和 ATS

由於版本 9,iOS 只會允許您的應用程式與預設實作最佳做法安全性的伺服器通訊。 值必須設定為 , Info.plist 才能與不安全的伺服器進行通訊。

注意

如果您的應用程式需要連線到不安全的網站,您應該一律使用 NSExceptionDomains 輸入網域作為例外狀況,而不是使用 完全 NSAllowsArbitraryLoads關閉 ATS。 NSAllowsArbitraryLoads 只應用於極端的緊急情況下。

下列示範如何啟用特定網域(在此案例中為 xamarin.com)略過 ATS 需求:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>xamarin.com</key>
            <dict>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSTemporaryExceptionMinimumTLSVersion</key>
                <string>TLSv1.1</string>
            </dict>
        </dict>
    </dict>
    ...
</key>

最佳做法是只讓某些網域略過 ATS,讓您能夠使用信任的網站,同時受益於未受信任網域上的額外安全性。 下列示範停用應用程式的 ATS 較不安全的方法:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads </key>
        <true/>
    </dict>
    ...
</key>

如需 iOS 9 中這項新功能的詳細資訊,請參閱 應用程式傳輸安全性

HTML 字串

如果您想要在程式代碼中動態呈現以動態方式定義的 HTML 字串,您必須建立 的 HtmlWebViewSource實例:

var browser = new WebView();
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = @"<html><body>
  <h1>Xamarin.Forms</h1>
  <p>Welcome to WebView.</p>
  </body></html>";
browser.Source = htmlSource;

WebView Displaying HTML String

在上述程式代碼中, @ 用來將 HTML 標示為 逐字字串常值,這表示會忽略大部分逸出字元。

注意

視 版面配置WebView而定,可能需要設定 WidthRequest 的 和 HeightRequest 屬性WebView,才能查看 HTML 內容。 例如,這是 在中 StackLayout的必要專案。

本機 HTML 內容

WebView 可以顯示內嵌在應用程式中的 HTML、CSS 和 JavaScript 內容。 例如:

<html>
  <head>
    <title>Xamarin Forms</title>
  </head>
  <body>
    <h1>Xamarin.Forms</h1>
    <p>This is an iOS web page.</p>
    <img src="XamarinLogo.png" />
  </body>
</html>

Css:

html,body {
  margin:0;
  padding:10;
}
body,p,h1 {
  font-family: Chalkduster;
}

請注意,上述 CSS 中指定的字型必須針對每個平臺自定義,因為並非所有平臺都有相同的字型。

若要使用 WebView來顯示本機內容,您必須像任何其他一樣開啟 HTML 檔案,然後將內容當做字串載入 至 HtmlHtmlWebViewSource屬性。 如需開啟檔案的詳細資訊,請參閱 使用檔案

下列螢幕快照顯示在每個平台上顯示本機內容的結果:

WebView Displaying Local Content

雖然已載入第一頁,但 WebView 不知道 HTML 的來源。 這是處理參考本機資源的頁面時發生問題。 可能發生的範例包括本機頁面彼此連結時、頁面會使用個別的 JavaScript 檔案,或 CSS 樣式表單的頁面連結。

若要解決此問題,您必須告訴 WebView 在文件系統上尋找檔案的位置。 在所使用的 WebViewHtmlWebViewSource設定 BaseUrl 屬性,以執行此動作。

因為每個作業系統上的文件系統都不同,因此您必須判斷每個平臺上的URL。 Xamarin.Forms 會 DependencyService 公開 ,以在每個平臺上的運行時間解析相依性。

若要使用 DependencyService,請先定義可在每個平台上實作的介面:

public interface IBaseUrl { string Get(); }

請注意,在每個平台上實作 介面之前,應用程式將不會執行。 在一般專案中,請確定您記得使用 DependencyService來設定 BaseUrl

var source = new HtmlWebViewSource();
source.BaseUrl = DependencyService.Get<IBaseUrl>().Get();

接著必須提供每個平臺的介面實作。

iOS

在iOS上,Web內容應該位於專案的根目錄或具有建置動作 BundleResource 的資源目錄中,如下所示:

BaseUrl應該設定為主要套件組合的路徑:

[assembly: Dependency (typeof (BaseUrl_iOS))]
namespace WorkingWithWebview.iOS
{
  public class BaseUrl_iOS : IBaseUrl
  {
    public string Get()
    {
      return NSBundle.MainBundle.BundlePath;
    }
  }
}

Android

在 Android 上,使用建置動作 AndroidAsset 將 HTML、CSS 和影像放在 Assets 資料夾中,如下所示:

在 Android 上 BaseUrl ,應該設定為 "file:///android_asset/"

[assembly: Dependency (typeof(BaseUrl_Android))]
namespace WorkingWithWebview.Android
{
  public class BaseUrl_Android : IBaseUrl
  {
    public string Get()
    {
      return "file:///android_asset/";
    }
  }
}

在 Android 上, 您也可以透過屬性公開的目前 Android 內容來存取 Assets 資料夾中的 MainActivity.Instance 檔案:

var assetManager = MainActivity.Instance.Assets;
using (var streamReader = new StreamReader (assetManager.Open ("local.html")))
{
  var html = streamReader.ReadToEnd ();
}

通用 Windows 平台

在 通用 Windows 平台 (UWP) 專案上,將 HTML、CSS 和影像放在專案根目錄中,並將建置動作設定為 [內容]。

BaseUrl設定為 "ms-appx-web:///"

[assembly: Dependency(typeof(BaseUrl))]
namespace WorkingWithWebview.UWP
{
    public class BaseUrl : IBaseUrl
    {
        public string Get()
        {
            return "ms-appx-web:///";
        }
    }
}

WebView 支援瀏覽數個可供使用的方法和屬性:

  • GoForward() – 如果 CanGoForward 為 true,則呼叫 GoForward 會向前流覽至下一個瀏覽的頁面。
  • GoBack() – 如果 CanGoBack 為 true,呼叫 GoBack 會瀏覽至最後一個瀏覽的頁面。
  • CanGoBacktrue 如果有頁面可巡覽回 , false 則瀏覽器位於起始 URL。
  • CanGoForwardtrue 如果使用者已向後流覽,而且可以向前移至已瀏覽的頁面。

在頁面中, WebView 不支援多點觸控手勢。 請務必確定內容已針對行動裝置優化,且不需要縮放即可顯示。

應用程式通常會在 中 WebView顯示連結,而不是裝置的瀏覽器。 在這些情況下,允許一般流覽很有用,但當使用者在開始連結時回擊時,應用程式應該會返回一般應用程式檢視。

使用內建導覽方法和屬性來啟用此案例。

從建立瀏覽器檢視的頁面開始:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="WebViewSample.InAppBrowserXaml"
             Title="Browser">
    <StackLayout Margin="20">
        <StackLayout Orientation="Horizontal">
            <Button Text="Back" HorizontalOptions="StartAndExpand" Clicked="OnBackButtonClicked" />
            <Button Text="Forward" HorizontalOptions="EndAndExpand" Clicked="OnForwardButtonClicked" />
        </StackLayout>
        <!-- WebView needs to be given height and width request within layouts to render. -->
        <WebView x:Name="webView" WidthRequest="1000" HeightRequest="1000" />
    </StackLayout>
</ContentPage>

在程式代碼後置中:

public partial class InAppBrowserXaml : ContentPage
{
    public InAppBrowserXaml(string URL)
    {
        InitializeComponent();
        webView.Source = URL;
    }

    async void OnBackButtonClicked(object sender, EventArgs e)
    {
        if (webView.CanGoBack)
        {
            webView.GoBack();
        }
        else
        {
            await Navigation.PopAsync();
        }
    }

    void OnForwardButtonClicked(object sender, EventArgs e)
    {
        if (webView.CanGoForward)
        {
            webView.GoForward();
        }
    }
}

介紹完畢

WebView Navigation Buttons

事件

WebView 會引發下列事件,以協助您響應狀態的變更:

  • Navigating – WebView 開始載入新頁面時引發的事件。
  • Navigated – 載入頁面並停止瀏覽時引發的事件。
  • ReloadRequested – 提出要求以重載目前內容時引發的事件。

事件 WebNavigatingEventArgs 隨附 Navigating 的物件有四個屬性:

  • Cancel – 指出是否要取消導覽。
  • NavigationEvent – 引發的導覽事件。
  • Source – 執行巡覽的專案。
  • Url – 瀏覽目的地。

事件 WebNavigatedEventArgs 隨附 Navigated 的物件有四個屬性:

  • NavigationEvent – 引發的導覽事件。
  • Result – 使用列舉成員描述導覽 WebNavigationResult 的結果。 有效值為 CancelFailureSuccessTimeout
  • Source – 執行巡覽的專案。
  • Url – 瀏覽目的地。

如果您預期使用需要長時間載入的網頁,請考慮使用 NavigatingNavigated 事件來實作狀態指示器。 例如:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="WebViewSample.LoadingLabelXaml"
             Title="Loading Demo">
    <StackLayout>
        <!--Loading label should not render by default.-->
        <Label x:Name="labelLoading" Text="Loading..." IsVisible="false" />
        <WebView HeightRequest="1000" WidthRequest="1000" Source="https://dotnet.microsoft.com/apps/xamarin" Navigated="webviewNavigated" Navigating="webviewNavigating" />
    </StackLayout>
</ContentPage>

這兩個事件處理程式:

void webviewNavigating(object sender, WebNavigatingEventArgs e)
{
    labelLoading.IsVisible = true;
}

void webviewNavigated(object sender, WebNavigatedEventArgs e)
{
    labelLoading.IsVisible = false;
}

這會產生下列輸出(載入):

Screenshot shows WebView Navigating Event while loading.

完成載入:

Screenshot shows WebView Navigating Event after loading.

重載內容

WebViewReload具有可用來重載目前內容的方法:

var webView = new WebView();
...
webView.Reload();

Reload叫用 方法時,ReloadRequested會引發 事件,表示已提出重載目前內容的要求。

效能

熱門的網頁瀏覽器採用硬體加速轉譯和 JavaScript 編譯等技術。 在 Xamarin.Forms 4.4 之前,類別 Xamarin.FormsWebView 已在 UIWebView iOS 上實作 。 不過,此實作中有許多技術無法使用。 因此,由於 Xamarin.Forms 4.4, Xamarin.FormsWebView 類別會在 WkWebView iOS 上實作 ,其支援更快速流覽。

注意

在 iOS 上 WkWebViewRenderer ,具有接受自變數的 WkWebViewConfiguration 建構函式多載。 這可讓轉譯器在建立時設定。

基於相容性考慮,應用程式可以使用 iOS UIWebView 類別來實 Xamarin.FormsWebView作 。 將下列程式代碼新增至 應用程式的 iOS 平台專案中的 AssemblyInfo.cs 檔案,即可達成此目的:

// Opt-in to using UIWebView instead of WkWebView.
[assembly: ExportRenderer(typeof(Xamarin.Forms.WebView), typeof(Xamarin.Forms.Platform.iOS.WebViewRenderer))]

注意

在 Xamarin.Forms 5.0 中,已移除 類別 WebViewRenderer 。 因此, Xamarin.Forms 5.0 不包含 控制件的 UIWebView 參考。

WebView 根據預設,在Android上的速度會和內建瀏覽器一樣快。

UWP WebView 使用 Microsoft Edge 轉譯引擎。 桌面和平板電腦裝置應該會看到與使用 Edge 瀏覽器本身相同的效能。

權限

若要 WebView 運作,您必須確定已為每個平台設定許可權。 請注意,在某些平臺上, WebView 會以偵錯模式運作,但不適用於針對發行建置時。 這是因為在偵錯模式中,Visual Studio for Mac 預設會設定某些許可權,例如 Android 上的因特網存取許可權。

  • UWP – 顯示網路內容時需要因特網 (Client & Server) 功能。
  • Android – 只有在顯示來自網路的內容時才需要 INTERNET 。 本機內容不需要特殊許可權。
  • iOS – 不需要特殊許可權。

版面配置

與其他大部分檢視 Xamarin.Forms 不同,在 StackLayout 或 RelativeLayout 中包含 時, WebView 會要求 HeightRequestWidthRequest 指定 。 如果您無法指定這些屬性, WebView 將不會轉譯。

下列範例示範導致運作、轉譯的版面配置 WebView

具有 WidthRequest 和 HeightRequest 的 StackLayout:

<StackLayout>
    <Label Text="test" />
    <WebView Source="https://dotnet.microsoft.com/apps/xamarin"
        HeightRequest="1000"
        WidthRequest="1000" />
</StackLayout>

RelativeLayout 與 WidthRequest & HeightRequest:

<RelativeLayout>
    <Label Text="test"
        RelativeLayout.XConstraint= "{ConstraintExpression
                                      Type=Constant, Constant=10}"
        RelativeLayout.YConstraint= "{ConstraintExpression
                                      Type=Constant, Constant=20}" />
    <WebView Source="https://dotnet.microsoft.com/apps/xamarin"
        RelativeLayout.XConstraint="{ConstraintExpression Type=Constant,
                                     Constant=10}"
        RelativeLayout.YConstraint="{ConstraintExpression Type=Constant,
                                     Constant=50}"
        WidthRequest="1000" HeightRequest="1000" />
</RelativeLayout>

不含 WidthRequest 和 HeightRequest 的 AbsoluteLayout

<AbsoluteLayout>
    <Label Text="test" AbsoluteLayout.LayoutBounds="0,0,100,100" />
    <WebView Source="https://dotnet.microsoft.com/apps/xamarin"
      AbsoluteLayout.LayoutBounds="0,150,500,500" />
</AbsoluteLayout>

沒有 WidthRequest 和 HeightRequest 的網格線。 Grid 是幾個不需要指定要求高度和寬度的版面配置之一。

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="100" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Label Text="test" Grid.Row="0" />
    <WebView Source="https://dotnet.microsoft.com/apps/xamarin" Grid.Row="1" />
</Grid>

叫用 JavaScript

WebView 包含從 C# 叫用 JavaScript 函式的功能,並將任何結果傳回呼叫的 C# 程式代碼。 這是使用 WebView.EvaluateJavaScriptAsync 方法完成的,如下列 WebView 範例範例所示:

var numberEntry = new Entry { Text = "5" };
var resultLabel = new Label();
var webView = new WebView();
...

int number = int.Parse(numberEntry.Text);
string result = await webView.EvaluateJavaScriptAsync($"factorial({number})");
resultLabel.Text = $"Factorial of {number} is {result}.";

方法 WebView.EvaluateJavaScriptAsync 會評估指定為 自變數的 JavaScript,並以 傳回任何結果 string。 在此範例中 factorial ,會叫用 JavaScript 函式,因此會傳回 的因數 number 。 此 JavaScript 函式定義於載入的 WebView 本機 HTML 檔案中,如下列範例所示:

<html>
<body>
<script type="text/javascript">
function factorial(num) {
        if (num === 0 || num === 1)
            return 1;
        for (var i = num - 1; i >= 1; i--) {
            num *= i;
        }
        return num;
}
</script>
</body>
</html>

Cookie

您可以在 上 WebView設定 Cookie,然後透過 Web 要求傳送至指定的 URL。 這可藉由將 物件加入 CookieCookieContainer,然後設定為可系結屬性的值 WebView.Cookies 來完成。 下列程式代碼顯示下列範例:

using System.Net;
using Xamarin.Forms;
// ...

CookieContainer cookieContainer = new CookieContainer();
Uri uri = new Uri("https://dotnet.microsoft.com/apps/xamarin", UriKind.RelativeOrAbsolute);

Cookie cookie = new Cookie
{
    Name = "XamarinCookie",
    Expires = DateTime.Now.AddDays(1),
    Value = "My cookie",
    Domain = uri.Host,
    Path = "/"
};
cookieContainer.Add(uri, cookie);
webView.Cookies = cookieContainer;
webView.Source = new UrlWebViewSource { Url = uri.ToString() };

在此範例中,會將單 Cookie 一新增至 CookieContainer 對象,然後設定為 屬性的值 WebView.CookiesWebView當 傳送 Web 要求至指定的 URL 時,Cookie 會隨要求一起傳送。

UIWebView 淘汰和 App Store 拒絕 (ITMS-90809)

從 2020 年 4 月開始,Apple 將會拒絕仍在使用已UIWebView取代 API 的應用程式。 雖然 Xamarin.Forms 已切換 WKWebView 為預設值,但仍有二進位檔中舊版SDK的 Xamarin.Forms 參考。 目前的 iOS 連結器 行為不會移除此行為,因此當您提交至 App Store 時,已被取代 UIWebView 的 API 仍會顯示從您的應用程式參考。

重要

在 Xamarin.Forms 5.0 中,已移除 類別 WebViewRenderer 。 因此, Xamarin.Forms 5.0 不包含 控制件的 UIWebView 參考。

鏈接器預覽版本可用來修正此問題。 若要啟用預覽,您必須為連結器提供額外的自變數 --optimize=experimental-xforms-product-type

此作業的必要條件如下:

  • Xamarin.Forms 4.5 或更高版本。 Xamarin.Forms 如果您的應用程式使用 Material Visual,則需要 4.6 或更高版本。
  • Xamarin.iOS 13.10.0.17 或更高版本。 在 Visual Studio 中檢查您的 Xamarin.iOS 版本。 此版本的 Xamarin.iOS 隨附於 Visual Studio for Mac 8.4.1 和 Visual Studio 16.4.3。
  • 拿掉的 UIWebView參考。 您的程式代碼不應該有任何參考 UIWebView ,或使用的任何類別 UIWebView

如需偵測和移除 UIWebView 參考的詳細資訊,請參閱 UIWebView 淘汰

設定連結器

請遵循下列步驟,讓連結器移除 UIWebView 參考:

  1. 開啟 iOS 項目屬性 – 以滑鼠右鍵按下您的 iOS 專案,然後選擇 [ 屬性]。
  2. 流覽至 [iOS 組建] 區段 – 選取 [iOS 組建 ] 區段。
  3. 更新其他 mtouch 自變數 – 在 [其他 mtouch 自變數 ] 中新增此旗標 --optimize=experimental-xforms-product-type (除了可能已存在的任何值之外)。 注意:此旗標可與鏈接器行為設定為 [僅限 SDK] 或 [全部連結] 搭配運作。 如果基於任何原因,您在將連結器行為設定為 [全部] 時看到錯誤,這很可能是應用程式程式代碼或非連結器安全的第三方連結庫內發生問題。 如需連結器的詳細資訊,請參閱 連結 Xamarin.iOS 應用程式
  4. 更新所有組建組態 – 使用 視窗頂端的 [組態 ] 和 [平臺 ] 列表來更新所有組建組態。 要更新的最重要組態是 Release/i 電話 組態,因為這通常用來建立 App Store 提交的組建。

您可以在此螢幕快照中看到具有新旗標的視窗:

Setting the flag in the iOS Build section

現在,當您建立新的 (release) 組建並將其提交至 App Store 時,應該不會有關於已取代 API 的警告。