Xamarin.Forms WebView
WebView
是在您的應用程式中顯示 Web 和 HTML 內容的檢視:
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;
在上述程式代碼中, @
用來將 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 檔案,然後將內容當做字串載入 至 Html
的 HtmlWebViewSource
屬性。 如需開啟檔案的詳細資訊,請參閱 使用檔案。
下列螢幕快照顯示在每個平台上顯示本機內容的結果:
雖然已載入第一頁,但 WebView
不知道 HTML 的來源。 這是處理參考本機資源的頁面時發生問題。 可能發生的範例包括本機頁面彼此連結時、頁面會使用個別的 JavaScript 檔案,或 CSS 樣式表單的頁面連結。
若要解決此問題,您必須告訴 WebView
在文件系統上尋找檔案的位置。 在所使用的 WebView
上HtmlWebViewSource
設定 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
會瀏覽至最後一個瀏覽的頁面。 - CanGoBack –
true
如果有頁面可巡覽回 ,false
則瀏覽器位於起始 URL。 - CanGoForward –
true
如果使用者已向後流覽,而且可以向前移至已瀏覽的頁面。
在頁面中, 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 會引發下列事件,以協助您響應狀態的變更:
Navigating
– WebView 開始載入新頁面時引發的事件。Navigated
– 載入頁面並停止瀏覽時引發的事件。ReloadRequested
– 提出要求以重載目前內容時引發的事件。
事件 WebNavigatingEventArgs
隨附 Navigating
的物件有四個屬性:
Cancel
– 指出是否要取消導覽。NavigationEvent
– 引發的導覽事件。Source
– 執行巡覽的專案。Url
– 瀏覽目的地。
事件 WebNavigatedEventArgs
隨附 Navigated
的物件有四個屬性:
NavigationEvent
– 引發的導覽事件。Result
– 使用列舉成員描述導覽WebNavigationResult
的結果。 有效值為Cancel
、Failure
、Success
和Timeout
。Source
– 執行巡覽的專案。Url
– 瀏覽目的地。
如果您預期使用需要長時間載入的網頁,請考慮使用 Navigating
和 Navigated
事件來實作狀態指示器。 例如:
<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;
}
這會產生下列輸出(載入):
完成載入:
重載內容
WebView
Reload
具有可用來重載目前內容的方法:
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
會要求 HeightRequest
和 WidthRequest
指定 。 如果您無法指定這些屬性, 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
方法來完成:
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。 這可藉由將 物件加入 Cookie
至 CookieContainer
,然後設定為可系結屬性的值 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.Cookies
。 WebView
當 傳送 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
參考:
- 開啟 iOS 項目屬性 – 以滑鼠右鍵按下您的 iOS 專案,然後選擇 [ 屬性]。
- 流覽至 [iOS 組建] 區段 – 選取 [iOS 組建 ] 區段。
- 更新其他 mtouch 自變數 – 在 [其他 mtouch 自變數 ] 中新增此旗標
--optimize=experimental-xforms-product-type
(除了可能已存在的任何值之外)。 注意:此旗標可與鏈接器行為設定為 [僅限 SDK] 或 [全部連結] 搭配運作。 如果基於任何原因,您在將連結器行為設定為 [全部] 時看到錯誤,這很可能是應用程式程式代碼或非連結器安全的第三方連結庫內發生問題。 如需連結器的詳細資訊,請參閱 連結 Xamarin.iOS 應用程式。 - 更新所有組建組態 – 使用 視窗頂端的 [組態 ] 和 [平臺 ] 列表來更新所有組建組態。 要更新的最重要組態是 Release/iPhone 組態,因為這通常用來建立 App Store 提交的組建。
您可以在此螢幕快照中看到具有新旗標的視窗:
現在,當您建立新的 (release) 組建並將其提交至 App Store 時,應該不會有關於已取代 API 的警告。