WebView
.NET Multi-platform App UI (.NET MAUI) WebView 可在应用中显示远程网页、本地 HTML 文件和 HTML 字符串。 WebView 显示的内容包含对级联样式表 (CSS) 和 JavaScript 的支持。 默认情况下,.NET MAUI 项目包含 WebView 显示远程网页所需的平台权限。
WebView 定义以下属性:
- Cookies,类型为
CookieContainer
,为 Cookie 集合提供存储。 - CanGoBack,类型为
bool
,指示用户是否可导航到之前的页面。 这是只读属性。 - CanGoForward,类型为
bool
,指示用户是否可以向前导航。 这是只读属性。 - Source,类型为
WebViewSource
,表示 WebView 的显示位置。 - UserAgent,类型为
string
,表示用户代理。 默认值为基础平台浏览器的用户代理,如果无法确定,则为null
。
这些属性由 BindableProperty 对象提供支持,表示它们可以是数据绑定的目标,并可以设置样式。
可以将 Source
属性设置为均派生自 WebViewSource
的 UrlWebViewSource
对象或 HtmlWebViewSource
对象。 UrlWebViewSource
用于加载使用 URL 指定的网页,而 HtmlWebViewSource
对象用于加载本地 HTML 文件或本地 HTML。
WebView 定义在页面导航启动时引发的 Navigating
事件,以及在页面导航完成时引发的 Navigated
事件。 Navigating
事件附带的 WebNavigatingEventArgs
对象定义类型为 bool
的 Cancel
属性,可用于取消导航。 Navigated
事件附带的 WebNavigatedEventArgs
对象定义类型为 WebNavigationResult
的 Result
属性,用于指示导航结果。
WebView 定义以下事件:
Navigating
,页面导航开始时引发。 此事件附带的WebNavigatingEventArgs
对象定义Cancel
属性,类型为bool
,该属性可用于取消导航。Navigated
,页面导航完成时引发。 此事件附带的WebNavigatedEventArgs
对象定义Result
属性,类型为WebNavigationResult
,该属性指示导航结果。ProcessTerminated
,WebView 进程意外结束时引发。 此事件附带的WebViewProcessTerminatedEventArgs
对象定义特定于平台的属性,这些属性指示进程失败的原因。
重要
当 WebView 包含在 HorizontalStackLayout、StackLayout 或 VerticalStackLayout 中时,它必须指定其 HeightRequest 和 WidthRequest 属性。 如果无法指定这些属性,则 WebView 不会呈现。
显示网页
若要显示远程网页,需将 Source
属性设置为指定 URI 的 string
:
<WebView Source="https://learn.microsoft.com/dotnet/maui" />
等效 C# 代码如下:
WebView webvView = new WebView
{
Source = "https://learn.microsoft.com/dotnet/maui"
};
URI 的格式必须完全符合指定的协议。
注意
尽管 Source
属性的类型为 WebViewSource
,但可以将该属性设置为基于字符串的 URI。 这是因为 .NET MAUI 包含类型转换器和隐式转换运算符,可用于将基于字符串的 URI 转换为 UrlWebViewSource
对象。
在 iOS 和 Mac Catalyst 上配置应用传输安全
自版本 9 起,iOS 将仅允许应用与安全服务器通信。 应用必须选择启用与不安全服务器的通信。
以下 Info.plist 配置展示了如何使特定域绕过 Apple 传输安全 (ATS) 要求:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>mydomain.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>
最佳做法是仅允许特定域绕过 ATS,从而允许使用受信任的站点,同时受益于针对不受信任域的额外安全保护。
以下 Info.plist 配置展示了如何为应用禁用 ATS:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
重要说明
如果应用需要连接到不安全的网站,应始终使用 NSExceptionDomains
密钥将域作为例外输入,而不是使用 NSAllowsArbitraryLoads
密钥完全关闭 ATS。
显示本地 HTML
若要显示内联 HTML,需将 Source
属性设置为 HtmlWebViewSource
对象:
<WebView>
<WebView.Source>
<HtmlWebViewSource Html="<HTML><BODY><H1>.NET MAUI</H1><P>Welcome to WebView.</P></BODY><HTML>" />
</WebView.Source>
</WebView>
在 XAML 中,由于对 <
和 >
符号进行字符转义,HTML 字符串可能变得不可读取。 因此,为了提高可读性,可以在 CDATA
部分中内联 HTML:
<WebView>
<WebView.Source>
<HtmlWebViewSource>
<HtmlWebViewSource.Html>
<![CDATA[
<HTML>
<BODY>
<H1>.NET MAUI</H1>
<P>Welcome to WebView.</P>
</BODY>
</HTML>
]]>
</HtmlWebViewSource.Html>
</HtmlWebViewSource>
</WebView.Source>
</WebView>
等效 C# 代码如下:
WebView webView = new WebView
{
Source = new HtmlWebViewSource
{
Html = @"<HTML><BODY><H1>.NET MAUI</H1><P>Welcome to WebView.</P></BODY></HTML>"
}
};
显示本地 HTML 文件
若要显示本地 HTML 文件,需将该文件添加到应用项目的 Resources\Raw 文件夹中,并将其生成操作设置为 MauiAsset。 然后,可以从内联 HTML(在设置为 Source
属性值的 HtmlWebViewSource
对象中定义)加载此文件:
<WebView>
<WebView.Source>
<HtmlWebViewSource>
<HtmlWebViewSource.Html>
<![CDATA[
<html>
<head>
</head>
<body>
<h1>.NET MAUI</h1>
<p>The CSS and image are loaded from local files!</p>
<p><a href="localfile.html">next page</a></p>
</body>
</html>
]]>
</HtmlWebViewSource.Html>
</HtmlWebViewSource>
</WebView.Source>
</WebView>
本地 HTML 文件可以加载级联样式表 (CSS)、JavaScript 和图像(如果也已使用 MauiAsset 生成操作将它们添加到应用项目中)。
要详细了解原始资产,请参阅原始资产。
重新加载内容
WebView 包含可以调用以重新加载其源内容的 Reload
方法:
WebView webView = new WebView();
...
webView.Reload();
调用 Reload
方法时,将触发 ReloadRequested
事件,指示已发出重新加载当前内容的请求。
执行导航
WebView 支持使用 GoBack
和 GoForward
方法以编程方式导航。 这些方法支持在 WebView 页面堆栈中导航,并且只有在检查 CanGoBack
和 CanGoForward
属性的值后才调用:
WebView webView = new WebView();
...
// Go backwards, if allowed.
if (webView.CanGoBack)
{
webView.GoBack();
}
// Go forwards, if allowed.
if (webView.CanGoForward)
{
webView.GoForward();
}
当页面导航在 WebView 中以编程方式启动或由用户启动时,会发生以下事件:
Navigating
,页面导航启动时引发。Navigating
事件附带的WebNavigatingEventArgs
对象定义类型为bool
的Cancel
属性,可用于取消导航。Navigated
,页面导航完成时引发。Navigated
事件附带的WebNavigatedEventArgs
对象定义类型为WebNavigationResult
的Result
属性,用于指示导航结果。
处理 Android 上的权限
浏览到请求访问设备的录制硬件(如摄像头或麦克风)的页面时,必须由 WebView 控件授予权限。 WebView
控件使用 Android 上的 Android.Webkit.WebChromeClient 类型来响应权限请求。 但是,.NET MAUI 提供的 WebChromeClient
实现将忽略权限请求。 你必须创建继承自 MauiWebChromeClient
的新类型并审批权限请求。
重要说明
使用此方法自定义 WebView
以审批权限请求时,必须使用 Android API 26 或更高版本。
从网页发送给 WebView
控件的权限请求不同于从 .NET MAUI 应用发送给用户的权限请求。 .NET MAUI 应用权限由用户请求和审批,针对整个应用。 WebView
控件依赖于应用访问硬件的能力。 为了说明此概念,请考虑请求访问设备摄像头的网页。 即使该请求得到 WebView
控件的批准,但如果 .NET MAUI 应用未从用户获得访问摄像头的权限,网页也无法访问摄像头。
以下步骤演示了如何从 WebView
控件截获使用摄像头的权限请求。 如果尝试使用麦克风,则步骤将类似,区别在于将使用与麦克风相关的权限,而不是与摄像头相关的权限。
首先,将所需的应用权限添加到 Android 清单。 打开 Platforms/Android/AndroidManifest.xml 文件,并在
manifest
节点中添加以下内容:<uses-permission android:name="android.permission.CAMERA" />
在应用中的某个时间点(例如加载包含
WebView
控件的页面时),会提出权限请求,要求用户允许应用访问摄像头。private async Task RequestCameraPermission() { PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.Camera>(); if (status != PermissionStatus.Granted) await Permissions.RequestAsync<Permissions.Camera>(); }
将以下类添加到 Platforms/Android 文件夹,更改根命名空间以匹配项目的命名空间:
using Android.Webkit; using Microsoft.Maui.Handlers; using Microsoft.Maui.Platform; namespace MauiAppWebViewHandlers.Platforms.Android; internal class MyWebChromeClient: MauiWebChromeClient { public MyWebChromeClient(IWebViewHandler handler) : base(handler) { } public override void OnPermissionRequest(PermissionRequest request) { // Process each request foreach (var resource in request.GetResources()) { // Check if the web page is requesting permission to the camera if (resource.Equals(PermissionRequest.ResourceVideoCapture, StringComparison.OrdinalIgnoreCase)) { // Get the status of the .NET MAUI app's access to the camera PermissionStatus status = Permissions.CheckStatusAsync<Permissions.Camera>().Result; // Deny the web page's request if the app's access to the camera is not "Granted" if (status != PermissionStatus.Granted) request.Deny(); else request.Grant(request.GetResources()); return; } } base.OnPermissionRequest(request); } }
在前面的代码片段中,
MyWebChromeClient
类继承自MauiWebChromeClient
,并替代OnPermissionRequest
方法来截获网页权限请求。 将检查每个权限项,以确定是否与表示摄像头的PermissionRequest.ResourceVideoCapture
字符串常量匹配。 如果摄像头权限匹配,则代码将检查以确定应用是否有权使用摄像头。 如果有权限,则会允许网页的请求。使用 Android 的
WebView
控件上的 SetWebChromeClient 方法将 Chrome 客户端设置为MyWebChromeClient
。 以下两个项演示了如何设置 Chrome 客户端:通过使用名为
theWebViewControl
的 .NET MAUIWebView
控件,可以直接在平台视图(即 Android 控件)上设置 Chrome 客户端:((IWebViewHandler)theWebViewControl.Handler).PlatformView.SetWebChromeClient(new MyWebChromeClient((IWebViewHandler)theWebViewControl.Handler));
还可以使用处理程序属性映射来强制所有
WebView
控件使用 Chrome 客户端。 有关详细信息,请参阅处理程序。当应用启动时,应调用以下代码片段的
CustomizeWebViewHandler
方法,例如在MauiProgram.CreateMauiApp
方法中。private static void CustomizeWebViewHandler() { #if ANDROID26_0_OR_GREATER Microsoft.Maui.Handlers.WebViewHandler.Mapper.ModifyMapping( nameof(Android.Webkit.WebView.WebChromeClient), (handler, view, args) => handler.PlatformView.SetWebChromeClient(new MyWebChromeClient(handler))); #endif }
设置 Cookie
可以在 WebView 上设置 Cookie,以便将其与 Web 请求一起发送到指定的 URL。 通过将 Cookie
对象添加到 CookieContainer
来设置 Cookie,然后将容器设置为 WebView.Cookies
可绑定属性的值。 以下代码演示了一个示例:
using System.Net;
CookieContainer cookieContainer = new CookieContainer();
Uri uri = new Uri("https://learn.microsoft.com/dotnet/maui", UriKind.RelativeOrAbsolute);
Cookie cookie = new Cookie
{
Name = "DotNetMAUICookie",
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() };
在此示例中,将向 CookieContainer
对象添加一个 Cookie
,然后将其设置为 WebView.Cookies
属性的值。 当 WebView 向指定的 URL 发送 Web 请求时,将随请求一起发送 Cookie。
调用 JavaScript
WebView 包含从 C# 调用 JavaScript 函数并将任何结果返回给执行调用的 C# 代码的功能。 此互操作可通过 EvaluateJavaScriptAsync
方法完成,如以下示例所示:
Entry numberEntry = new Entry { Text = "5" };
Label resultLabel = new Label();
WebView 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>
在 iOS 和 Mac Catalyst 上配置本机 WebView
本机 WebView 控件是 iOS 和 Mac Catalyst 上派生自 WKWebView
的 MauiWKWebView
。 其中一个 MauiWKWebView
构造函数重载支持指定 WKWebViewConfiguration
对象,该对象提供有关如何配置 WKWebView
对象的信息。 典型的配置包括设置用户代理、指定可用于 Web 内容的 Cookie,以及将自定义脚本注入到 Web 内容中。
可以在应用中创建 WKWebViewConfiguration
对象,然后根据需要配置其属性。 或者,也可以调用静态 MauiWKWebView.CreateConfiguration
方法来检索 .NET MAUI 的 WKWebViewConfiguration
对象,然后对其进行修改。 然后,可以将 WKWebViewConfiguration
对象指定为 MauiWKWebView
构造函数重载的参数。
由于在 iOS 和 Mac Catalyst 上创建处理程序的平台视图后,就无法更改本机 WebView 的配置,因此应创建自定义处理程序工厂委托以对其进行修改:
#if IOS || MACCATALYST
using WebKit;
using CoreGraphics;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Handlers;
#endif
...
#if IOS || MACCATALYST
Microsoft.Maui.Handlers.WebViewHandler.PlatformViewFactory = (handler) =>
{
WKWebViewConfiguration config = MauiWKWebView.CreateConfiguration();
config.ApplicationNameForUserAgent = "MyProduct/1.0.0";
return new MauiWKWebView(CGRect.Empty, (WebViewHandler)handler, config);
};
#endif
注意
在应用中显示 WebView 之前,应使用 WKWebViewConfiguration
对象配置 MauiWKWebView
。 执行此操作的适当位置位于应用的启动路径中,例如 MauiProgram.cs 或 App.xaml.cs。
在 iOS 和 Mac Catalyst 上设置媒体播放首选项
默认情况下,会为 iOS 和 Mac Catalyst 上的 WebView 启用 HTML5 视频的内联媒体播放,包括自动播放和画中画。 若要更改默认设置或设置其他媒体播放首选项,应创建自定义处理程序工厂委托,因为创建处理程序的平台视图后,就无法更改媒体播放首选项。 下面的代码展示了执行此操作的示例:
#if IOS || MACCATALYST
using WebKit;
using CoreGraphics;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Handlers;
#endif
...
#if IOS || MACCATALYST
Microsoft.Maui.Handlers.WebViewHandler.PlatformViewFactory = (handler) =>
{
WKWebViewConfiguration config = MauiWKWebView.CreateConfiguration();
// True to play HTML5 videos inliine, false to use the native full-screen controller.
config.AllowsInlineMediaPlayback = false;
// True to play videos over AirPlay, otherwise false.
config.AllowsAirPlayForMediaPlayback = false;
// True to let HTML5 videos play Picture in Picture.
config.AllowsPictureInPictureMediaPlayback = false;
// Media types that require a user gesture to begin playing.
config.MediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypes.All;
return new MauiWKWebView(CGRect.Empty, (WebViewHandler)handler, config);
};
#endif
有关在 iOS 上配置 WebView 的详细信息,请参阅在 iOS 和 Mac Catalyst 上配置本机 WebView。
在 Mac Catalyst 上检查 WebView
若要在 Mac Catalyst 上使用 Safari 开发人员工具检查 WebView 的内容,需将以下代码添加到应用:
#if MACCATALYST
Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping("Inspect", (handler, view) =>
{
if (OperatingSystem.IsMacCatalystVersionAtLeast(16, 6))
handler.PlatformView.Inspectable = true;
});
#endif
此代码自定义 Mac Catalyst 上的 WebViewHandler
属性映射器,以使 WebView 内容可由 Safari 开发人员工具检查。 有关处理程序的详细信息,请参阅处理程序。
若要在 Mac Catalyst 应用中使用 Safari 开发人员工具:
- 在 Mac 上打开 Safari。
- 在 Safari 中,选中“Safari > 设置 > 高级 > 在菜单栏中显示‘开发’菜单”复选框。
- 运行 .NET MAUI Mac Catalyst 应用。
- 在 Safari 中,选择“开发 > {Device name}”菜单,其中
{Device name}
占位符是设备名称,如Macbook Pro
。 然后选择应用名称下的条目,该条目还会突出显示正在运行的应用。 这会导致“Web 检查器”窗口出现。
启动系统浏览器
可以使用由 Microsoft.Maui.Essentials
提供的 Launcher
类在系统 Web 浏览器中打开 URI。 调用启动器的 OpenAsync
方法并传入表示要打开的 URI 的 string
或 Uri
参数:
await Launcher.OpenAsync("https://learn.microsoft.com/dotnet/maui");
有关详细信息,请参阅启动器。