本文共 4649 字,大约阅读时间需要 15 分钟。
在Flutter中使用webview,在中查看,有几个组件都可以使用webview
本文使用的是,它是Flutter团队开发的,目前还不是正式版,但已经可以使用。在iOS中底层调用的是WKWebView
,在Android中底层调用的是WebView
。
WebView( initialUrl: "https://flutterchina.club/", //JS执行模式 是否允许JS执行 javascriptMode: JavascriptMode.unrestricted, )
io.flutter.embedded_views_preview YES
第三步不可少,否则会报错。
在调用之前 先看一下WebView的其他参数:
WebView创建完成时调用
onWebViewCreated
, 要显示的url
initialUrl
JS执行模式 默认是不调用
javascriptMode = JavascriptMode.disabled
使用javascriptChannel JS可以调用Flutter
javascriptChannels
拦截请求
navigationDelegate
手势
gestureRecognizers
页面加载完成
onPageFinished
通过WebViewController
调用evaluateJavascript
方法,即可调用JS。
了解了每个参数的作用之后,交互就看似简单了。
Flutter调用JS的流程:
WebView
创建完成时在onWebViewCreated
中,获取到WebViewController
实例。onPageFinished
之后,通过WebViewController
的evaluateJavascript
方法调用JS。evaluateJavascript
返回的是Future<String>
,通过Future
可以获取到JS的返回结果。示例代码: 在页面加载完成之后,获取网页标题,并显示在导航栏上。
WebView( initialUrl: "https://flutterchina.club/", //JS执行模式 是否允许JS执行 javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (controller) { _controller = controller; }, onPageFinished: (url) { _controller.evaluateJavascript("document.title").then((result){ setState(() { _title = result; }); } ); }, )
效果:
JS调用Flutter主要看剩下的两个参数:
javascriptChannels
navigationDelegate
这两个参数都可以从JS调用Flutter,可以单独使用,也可以混合使用。
javascriptChannels
类似于往JS中注册方法,这些方法名要和web端约定好。
javascriptChannels
参数接受Set<JavascriptChannel>
一个成员类型为JavascriptChannel
的Set集合。
来看一下JavascriptChannel
的用法:
JavascriptChannel( name: "share", onMessageReceived: (JavascriptMessage message) { print("参数为: ${message.message}"); })
在JS端就可以调用share
方法,同时可以传递参数,在Flutter中通过JavascriptMessage
可以获取到参数。
navigationDelegate: (NavigationRequest request) { //对于需要拦截的操作 做判断 if(request.url.startsWith("myapp://")) { print("即将打开 ${request.url}"); //做拦截处理 //pushto.... Application.push(context, request.url); return NavigationDecision.prevent; } //不需要拦截的操作 return NavigationDecision.navigate;} ,
例如想要通过webview打开app的原生页面,通过约定好的链接,拦截到指定链接后可跳转到原生页面。
完整示例代码:
import 'package:flutter/cupertino.dart';import 'package:webview_flutter/webview_flutter.dart';class WebViewPage extends StatefulWidget { @override _WebViewPageState createState() => _WebViewPageState();}class _WebViewPageState extends State{ WebViewController _controller; String _title = "webview"; @override Widget build(BuildContext context) { return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: Text("$_title"), ), child: SafeArea( child: WebView( initialUrl: "https://flutterchina.club/", //JS执行模式 是否允许JS执行 javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (controller) { _controller = controller; }, onPageFinished: (url) { _controller.evaluateJavascript("document.title").then((result){ setState(() { _title = result; }); } ); }, navigationDelegate: (NavigationRequest request) { if(request.url.startsWith("myapp://")) { print("即将打开 ${request.url}"); return NavigationDecision.prevent; } return NavigationDecision.navigate; } , javascriptChannels: [ JavascriptChannel( name: "share", onMessageReceived: (JavascriptMessage message) { print("参数: ${message.message}"); } ), ].toSet(), ), ), ); }}
可能已经有同学看出来了,JS调用Flutter时,JS获取不到Flutter的返回值,目前还没有找到直接的解决办法,但可以通过迂回的方法解决。
下面提供两种思路:
JavascriptChannel( name: "share", onMessageReceived: (JavascriptMessage message) { print("参数: ${message.message}"); String callbackname = message.message; //实际应用中要通过map通过key获取 String data = "收到消息调用了"; String script = "$callbackname($data)"; _controller.evaluateJavascript(script); } )
2.在网页加载成功后,把JS需要获取的Flutter的值,注入到widow上, 在JS中就可以通过widow获取到相应的值。
String script = "window.isLogin=是否登录"; _controller.evaluateJavascript(script).then((result){ });作者:王大妈啊 链接:https://www.jianshu.com/p/4aabe453eb26 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。