在Flutter中使用webview,在pub.dev中查看,有几个组件均可以使用webviewjavascript
本文使用的是webview_flutter,它是Flutter团队开发的,目前还不是正式版,但已经可使用。在iOS中底层调用的是WKWebView
,在Android中底层调用的是WebView
。java
WebView(
initialUrl: "https://flutterchina.club/",
//JS执行模式 是否容许JS执行
javascriptMode: JavascriptMode.unrestricted,
)
复制代码
<key>io.flutter.embedded_views_preview</key>
<string>YES</string>
复制代码
第三步不可少,不然会报错。ios
在调用以前 先看一下WebView的其余参数:web
WebView建立完成时调用 onWebViewCreated
,bash
要显示的url initialUrl
app
JS执行模式 默认是不调用 javascriptMode = JavascriptMode.disabled
ide
使用javascriptChannel JS能够调用Flutter javascriptChannels
ui
拦截请求 navigationDelegate
lua
手势 gestureRecognizers
url
页面加载完成 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<WebViewPage> {
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>[
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);
}
)
复制代码
String script = "window.isLogin=是否登陆";
_controller.evaluateJavascript(script).then((result){
}
);
复制代码