.NET MAUI WebView无法打开外部链接,Navigating事件未触发求助
问题详情
使用Visual Studio 2022开发包含WebView控件的.NET MAUI移动应用,源网站mywebsite.com加载正常,内部链接可正常工作。需求是点击外部链接(如microsoft.com)时,在手机默认浏览器打开该网站,但目前点击任何外部链接均无反应——无论HTML中target属性设为_blank还是其他值,Navigating事件都不会触发。点击mywebsite.com内部链接时,Navigating事件可正常触发,已尝试相关解决方案但无效。
代码示例
MainPage.xaml.cs
public MainPage() { InitializeComponent(); // 订阅Navigating事件 proteoWebView.Navigating += OnNavigating; // 订阅Navigated事件 proteoWebView.Navigated += OnNavigated; } private void OnNavigating(object sender, WebNavigatingEventArgs e) { // 检查是否为外部链接 if (!e.Url.StartsWith("https://mywebsite.com")) { // 取消WebView内的导航 e.Cancel = true; // 在默认浏览器打开链接 Launcher.TryOpenAsync(e.Url); } }
MainPage.xaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="ProteoApp.MainPage" NavigationPage.HasNavigationBar="False"> <Grid> <WebView x:Name="proteoWebView" Source="https://mywebsite.com" Grid.Row="0" Grid.Column="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"/> </Grid> </ContentPage>
开发环境
- Visual Studio 2022
- .NET 7.0
- 问题出现于Pixel 5 – API 33(Android 13.0)模拟器
解决方案
针对Android平台,target="_blank"的链接默认不会触发WebView的Navigating事件,需要通过自定义WebView渲染器拦截新窗口请求:
1. Android平台自定义渲染器
在Android项目中创建以下类:
using Android.Webkit; using Microsoft.Maui.Controls.Compatibility.Platform.Android; using Microsoft.Maui.Controls.Platform; [assembly: ExportRenderer(typeof(WebView), typeof(CustomWebViewRenderer))] namespace ProteoApp.Platforms.Android { public class CustomWebViewRenderer : WebViewRenderer { public CustomWebViewRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) { base.OnElementChanged(e); if (Control != null) { Control.SetWebViewClient(new CustomWebViewClient()); Control.SetWebChromeClient(new CustomWebChromeClient()); } } } public class CustomWebViewClient : WebViewClient { public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request) { var url = request.Url.ToString(); if (!url.StartsWith("https://mywebsite.com")) { _ = Launcher.TryOpenAsync(url); return true; } return base.ShouldOverrideUrlLoading(view, request); } } public class CustomWebChromeClient : WebChromeClient { public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Message resultMsg) { var newWebView = new Android.Webkit.WebView(view.Context); newWebView.SetWebViewClient(new CustomWebViewClient()); var transport = (WebView.WebViewTransport)resultMsg.Obj; transport.WebView = newWebView; resultMsg.SendToTarget(); return true; } } }
2. 确认Android权限
确保AndroidManifest.xml中已添加互联网权限:
<uses-permission android:name="android.permission.INTERNET" />
3. (可选)iOS平台适配
如果需要支持iOS,创建iOS自定义渲染器:
using WebKit; using Microsoft.Maui.Controls.Compatibility.Platform.iOS; using Microsoft.Maui.Controls.Platform; [assembly: ExportRenderer(typeof(WebView), typeof(CustomWebViewRenderer))] namespace ProteoApp.Platforms.iOS { public class CustomWebViewRenderer : WebViewRenderer { protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) { base.OnElementChanged(e); if (Control != null) { var webView = Control as WKWebView; webView.Configuration.Preferences.JavaScriptEnabled = true; webView.NavigationDelegate = new CustomNavigationDelegate(); } } } public class CustomNavigationDelegate : WKNavigationDelegate { public override void DecidePolicy(WKWebView webView, WKNavigationAction navigationAction, Action<WKNavigationActionPolicy> decisionHandler) { var url = navigationAction.Request.Url.ToString(); if (!url.StartsWith("https://mywebsite.com")) { _ = Launcher.TryOpenAsync(url); decisionHandler(WKNavigationActionPolicy.Cancel); return; } decisionHandler(WKNavigationActionPolicy.Allow); } } }
逻辑说明
- Android端:
OnCreateWindow处理target="_blank"的新窗口请求,通过临时WebView绑定自定义WebViewClient拦截链接;ShouldOverrideUrlLoading拦截所有导航请求,判断外部链接后跳转至默认浏览器。 - iOS端:通过
WKNavigationDelegate的DecidePolicy方法拦截导航请求,实现相同的外部链接跳转逻辑。
内容的提问来源于stack exchange,提问作者Antelion
相关产品推荐
相关产品推荐

