在Flutter中使用webview,在pub.dev中查看,有几个组件都可以使用webview
本文使用的是webview_flutter,它是Flutter团队开发的,目前还不是正式版,但已经可以使用。在iOS中底层调用的是WKWebView
,在Android中底层调用的是WebView
。
WebView(
initialUrl: "https://flutterchina.club/",
//JS执行模式 是否允许JS执行
javascriptMode: JavascriptMode.unrestricted,
)
io.flutter.embedded_views_preview
YES
第三步不可少,否则会报错。
在调用之前 先看一下WebView的其他参数:
WebView创建完成时调用onWebViewCreated
,
要显示的urlinitialUrl
JS执行模式 默认是不调用javascriptMode = JavascriptMode.disabled
使用javascriptChannel JS可以调用FlutterjavascriptChannels
拦截请求navigationDelegate
手势gestureRecognizers
页面加载完成onPageFinished
通过WebViewController
调用evaluateJavascript
方法,即可调用JS。
了解了每个参数的作用之后,交互就看似简单了。
Flutter调用JS的流程:
WebView
创建完成时在onWebViewCreated
中,获取到WebViewController
实例。onPageFinished
之后,通过WebViewController
的evaluateJavascript
方法调用JS。evaluateJavascript
返回的是Future
,通过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
的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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。