最近用VS2022的MAUI开发一个安卓应用,一切都很顺利,但在操作WebView的控件上,发现C#并不能执行WebView控件嵌套html页面里面js的print()打印功能,查了下,好象安卓本身也不支持,需要改写 WebView控件的 ShouldOverrideUrlLoading方法,俱体这样
假设你的webView控件命名为:webView那么,第一步,新建一个类,这个类必须放在安卓专有的目录下:我是放在 项目\Platforms\Android\CustomWebViewClient.cs
CustomWebViewClient.cs源码如下:
using Android.Content;
using Android.Print;
using Android.Webkit;
using Java.Net;
using Microsoft.Maui.Platform;
using Newtonsoft.Json;
using System.Net;
namespace myapp
{
public class CustomWebViewClient : WebViewClient
{
public override void OnPageFinished(Android.Webkit.WebView view, string url)
{
base.OnPageFinished(view, url);
view.Settings.JavaScriptEnabled = true;//启用js
}
public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
{
string url = request.Url.ToString();
if (url.StartsWith("weixin://"))
{
Launcher.OpenAsync(new Uri(url));
return true; // 表示已处理 URL 加载
}
else if (url.Contains("Logout"))
{
// 在这里实现跳转到 Login 页面
var loginPage = new Login(); // 创建登录页面实例
App.Current!.MainPage = new NavigationPage(loginPage); // 设置登录页面为当前页面
return true; // 表示已处理 URL 加载
}
//启动打印
else if (url.Contains("print"))
{
var printManager = Platform.CurrentActivity.GetSystemService(Context.PrintService) as PrintManager;
PrintDocumentAdapter printAdapter = view.CreatePrintDocumentAdapter("MyDocument");
printManager.Print("Document", printAdapter, new PrintAttributes.Builder().Build());
return true; // 表示已处理 URL 加载
}
return false; // 没有处理 URL 加载,让 WebView 正常加载
}
}
}
第二步,让你的vewView控件加载这个类
建一个只有安卓才能运行的方法(其实maui开发IOS也不现实,因为还需要你有台mac,还要手动打开XCODE,还要在mac调用他的模拟器,更至命的是开发出来的布局惨不忍睹,安卓应用还可以!):
注意里面的webView就是对应你要操作的WebView控件名,这个要换成你自己的控件名
#if ANDROID
private void OnWebViewHandlerChanged(object sender, EventArgs e)
{
if (webView.Handler is Microsoft.Maui.Handlers.WebViewHandler handler)
{
Android.Webkit.WebView nativeWebView = (Android.Webkit.WebView)handler.PlatformView;
nativeWebView.SetWebViewClient(new CustomWebViewClient());
}
}
#endif
第三步:在 构造函数里,俱体可以在InitializeComponent();下面加载这个OnWebViewHandlerChanged方法
#if ANDROID
webView.HandlerChanged += OnWebViewHandlerChanged;
#endif
第四步:利用js的 window.location.href = "****"; 就是你的webView嵌入的thml5页面 ,如果想跟C#交互,一定要利用这个 window.location,至于还有什么方法触发,目前不清楚,如果你想用JS的打印,你不能直接在html5 的js里面直接写print();这样无法触发ShouldOverrideUrlLoading,要写成这样window.location.href =‘print’, 这个print是你自定义的,并不是说一定要写成print才能触发打印功能,你可以写复杂一点,如myprint等等关键词,然后在C#遇到这个print关键字就会拦截触发ShouldOverrideUrlLoading里面的操作,启动安卓手机的打印功能,我总共加了三个,一个是跳转微信支付的页面,一个是跳转登录页面,然后就是打印功能
以上是html5页面跟C#互动的方法,准确的说是html5利用window.location.href 的值传参给C#页面,由C#改写的ShouldOverrideUrlLoading方法,判断url值作出判断来执行相关功能,执行完以后返回true,意思是告诉系统,我自己处理完毕了,不需要你再执行原来window.location.href...的代码了
至于C#怎么操作html5页面JS的方法和函数,注意不能直接调用print(),除了这个,一般的自定义方法,都可以,这个官方有现成的就是:
await webView.EvaluateJavaScriptAsync("yourAction();");
如果需要传参给html5页面,则需要这样写:
string title="warning";
string message="你还示登录";
string buttonText="退出";
string script = $"logOut({{ type: title: '{title}', message: '{message}', buttonText: '{buttonText}' }});";
await webView.EvaluateJavaScriptAsync(script);