.NET 6 MAUI中Shell应用与WebView双向通信实现及Xamarin代码迁移问题咨询
.NET MAUI中WebView与JavaScript双向互操作的实现方案
你提到的问题很典型——MAUI确实摒弃了Xamarin.Forms里的Renderer模式,改用更灵活的Handler架构,所以原来的WebViewRenderer等类不再适用,但完全可以实现双向通信的功能,下面是针对Android平台的可行方案:
1. 创建自定义HybridWebView控件
先定义一个继承自MAUI WebView的自定义控件,用来封装JS消息接收和调用JS的能力:
using Microsoft.Maui.Controls; namespace YourNamespace { public class HybridWebView : WebView { // 用于接收JS传递的消息 public static readonly BindableProperty MessageReceivedProperty = BindableProperty.Create(nameof(MessageReceived), typeof(Action<string>), typeof(HybridWebView)); public Action<string> MessageReceived { get => (Action<string>)GetValue(MessageReceivedProperty); set => SetValue(MessageReceivedProperty, value); } // 调用JS方法的异步方法 public async Task EvaluateJavaScriptAsync(string script) { await Handler.InvokeAsync("EvaluateJavaScript", script); } } }
2. 实现Android平台的自定义Handler
MAUI用Handler替代了Renderer,我们需要创建HybridWebViewHandler来处理Android端的WebView配置:
2.1 编写JS桥接类(JsBridge)
这个类和你之前的JsBridge逻辑类似,但要适配MAUI的Handler:
using Android.Webkit; using Java.Interop; namespace YourNamespace.Platforms.Android { public class JsBridge : Java.Lang.Object { private readonly WeakReference<HybridWebViewHandler> _handlerReference; public JsBridge(HybridWebViewHandler handler) { _handlerReference = new WeakReference<HybridWebViewHandler>(handler); } [JavascriptInterface] [Export("invokeCSharpAction")] public void InvokeAction(string data) { if (_handlerReference.TryGetTarget(out var handler) && handler.VirtualView is HybridWebView hybridWebView) { // 将JS消息传递给自定义控件的回调 hybridWebView.MessageReceived?.Invoke(data); } } } }
2.2 自定义WebViewClient
用来在页面加载完成后注入JS桥接函数:
using Android.Webkit; namespace YourNamespace.Platforms.Android { public class HybridWebViewClient : WebViewClient { private const string JsBridgeScript = "function invokeCSharpAction(data){jsBridge.invokeCSharpAction(data);}"; public override void OnPageFinished(WebView view, string url) { base.OnPageFinished(view, url); // 注入JS函数,让网页可以调用C#代码 view.EvaluateJavascript(JsBridgeScript, null); } } }
2.3 实现HybridWebViewHandler
继承自MAUI的WebViewHandler,配置WebView并绑定桥接:
using Microsoft.Maui.Handlers; using Android.Webkit; namespace YourNamespace.Platforms.Android { public class HybridWebViewHandler : WebViewHandler { // 继承MAUI默认的属性映射,可按需扩展 public static IPropertyMapper<IWebView, WebViewHandler> HybridMapper = new PropertyMapper<IWebView, WebViewHandler>(WebViewHandler.Mapper); public HybridWebViewHandler() : base(HybridMapper, CommandMapper) { } protected override WebView CreatePlatformView() { var webView = base.CreatePlatformView(); // 启用JavaScript webView.Settings.JavaScriptEnabled = true; // 设置自定义WebViewClient webView.SetWebViewClient(new HybridWebViewClient()); // 添加JS桥接接口 webView.AddJavascriptInterface(new JsBridge(this), "jsBridge"); return webView; } // 实现调用JS的方法,供自定义控件调用 public void EvaluateJavaScript(string script) { PlatformView?.EvaluateJavascript(script, null); } } }
3. 注册Handler到MAUI应用
在MauiProgram.cs中注册自定义Handler:
using Microsoft.Maui; using Microsoft.Maui.Hosting; using YourNamespace.Platforms.Android; namespace YourNamespace { public static class MauiProgram { public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureMauiHandlers(handlers => { #if ANDROID // 注册Android平台的自定义Handler handlers.AddHandler<HybridWebView, HybridWebViewHandler>(); #endif }); return builder.Build(); } } }
4. 使用自定义HybridWebView
在XAML中引用控件:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:YourNamespace" x:Class="YourNamespace.MainPage"> <local:HybridWebView x:Name="MyHybridWebView" Source="https://your-web-page-url" /> </ContentPage>
在代码后台处理消息和调用JS:
using Microsoft.Maui.Controls; namespace YourNamespace { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); // 监听JS传来的消息 MyHybridWebView.MessageReceived += (data) => { MainThread.BeginInvokeOnMainThread(() => { // 在UI线程处理消息 DisplayAlert("Received from JS", data, "OK"); }); }; } // 示例:调用JS方法 private async void CallJavaScriptButton_Clicked(object sender, EventArgs e) { await MyHybridWebView.EvaluateJavaScriptAsync("showMessage('Hello from MAUI!')"); } } }
补充说明
- 这个方案在MAUI正式版及预览后期版本都能正常工作,Handler是MAUI的核心扩展机制,完全替代了原有的Renderer模式
- 如果需要支持iOS平台,思路类似:使用
WKWebView的WKScriptMessageHandler来实现双向通信,同样通过自定义Handler配置 - 注意在Android中,
[JavascriptInterface]和[Export]属性需要确保正确引用Java.Interop包
内容的提问来源于stack exchange,提问作者HoloShaii
相关产品推荐
相关产品推荐

