如何在flutter_inappwebview中打开about:blank新窗口并获取内容
解决Flutter WebView中打印按钮新开空白窗口的问题
问题说明
网页中的打印按钮(对应HTML代码:
<button onclick="printInvoice(127)" class="btn btn-success btn-lg">print</button>
)在浏览器中点击会新开标签页显示收据,但在Flutter应用中点击后,新窗口URL为about:blank且无响应,使用以下代码时还出现URL为null的问题:
onCreateWindow: (controller, createWindowRequest) async { await controller.loadUrl(urlRequest: createWindowRequest.request); String newWindowContent = await controller.evaluateJavascript( source: 'document.documentElement.outerHTML;', ); print('New Window Content: $newWindowContent'); return true; },
解决方案
1. 用独立WebViewController监听内容加载
原网页的printInvoice函数大概率是先创建about:blank窗口,再通过JavaScript写入收据HTML内容。原代码直接复用当前controller加载空白请求,且立即执行evaluateJavascript,此时内容还未写入,导致获取失败。
修改为创建新的WebViewController处理新窗口,监听页面加载完成后再获取内容:
onCreateWindow: (controller, createWindowRequest) async { // 创建新的WebViewController处理新窗口 final newWebViewController = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted); // 监听页面加载完成,确保内容已写入 newWebViewController.onPageFinished.listen((url) async { if (url == 'about:blank') { // 等待JS完成内容写入(时长可根据网页实际情况调整) await Future.delayed(const Duration(milliseconds: 500)); String newWindowContent = await newWebViewController.evaluateJavascript( source: 'document.documentElement.outerHTML;', ); print('New Window Content: $newWindowContent'); // 这里可添加展示或打印内容的逻辑 } }); await newWebViewController.loadUrl(urlRequest: createWindowRequest.request); // 可选:用弹窗展示新窗口内容 showDialog( context: context, builder: (context) => AlertDialog( title: const Text('收据预览'), content: SizedBox( width: double.maxFinite, height: 600, child: WebViewWidget(controller: newWebViewController), ), ), ); return true; },
2. 直接拦截printInvoice函数(推荐)
如果能知晓printInvoice的具体逻辑,可注入JavaScript拦截该函数,直接获取收据内容,无需处理新窗口:
// 初始化WebViewController时注入拦截代码 WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..addJavaScriptChannel( 'PrintChannel', onMessageReceived: (JavaScriptMessage message) { // 接收收据HTML内容 String invoiceHtml = message.message; print('Invoice HTML: $invoiceHtml'); // 后续可用于展示或调用Flutter打印API }, ) ..loadRequest(Uri.parse('你的网页URL')) ..runJavascript(''' // 重写原printInvoice函数 window.printInvoice = function(id) { // 替换为原函数生成收据HTML的逻辑 const invoiceHtml = 原函数生成HTML的代码; PrintChannel.postMessage(invoiceHtml); // 如需保留原打印行为,可添加window.print() }; ''');
3. 检查WebView基础配置
确保开启JavaScript支持:
..setJavaScriptMode(JavaScriptMode.unrestricted)
若网页存在跨域内容,配置导航权限:
..setNavigationDelegate( NavigationDelegate( onNavigationRequest: (request) => NavigationDecision.navigate, ), )
内容的提问来源于stack exchange,提问作者Sushang Nirola
相关产品推荐
相关产品推荐

