flutter官方并没有提供WebView组件,不过官方的plugin库给我们提供了webview_flutter插件,集成到我们的项目中就可以使用了
一、集成
在项目的pubspec.yaml文件中添加一下代码
webview_flutter: ^0.3.19+6二、简单使用
var webUrl ="http://192.168.10.120:8081/test.html?time=${DateTime.now()};
return Scaffold(
appBar: AppBar(title: Text('WebView')),
body: Builder(builder: (BuildContext context) {
return WebView(
initialUrl: webUrl,
onWebViewCreated: (WebViewController controller) {
_controller = controller;
},
onPageStarted: (String url) {},
onPageFinished: (String url) {},
);
}));
}三、Js 调用Flutter(两种方法)
方法一、使用javascriptChannels发送消息
Flutter代码
定义javascriptChannels JavascriptChannel方法中的两个参数,name是和js协商的标记,onMessageReceived当js收到Flutter发送的消息时的回调
JavascriptChannel _alertJavascriptChannel(BuildContext context) { return JavascriptChannel( name: 'MyApp', onMessageReceived: (JavascriptMessage message) { //js 收到了Flutter发送的消息 showToast(message.message); }); } WebView( javascriptChannels: <JavascriptChannel>[ _alertJavascriptChannel(context), ].toSet(),js代码
<button onclick="callFlutter()">callFlutter</button> function callFlutter(){ // MyApp为Flutter定义的name MyApp.postMessage("JS调用了Flutter"); }
方法二、使用路由委托navigationDelegate拦截url
Flutter代码
在Flutter端,我们就可以在navigationDelegate回调中拦截这个符合js://webviewscheme的路由地址了:navigationDelegate: (NavigationRequest request) { if (request.url.startsWith('js://html')) { showToast('JS调用了Flutter By navigationDelegate'); print('blocking navigation to $request}'); return NavigationDecision.prevent; //阻止路由替换 } print('allowing navigation to $request'); return NavigationDecision.navigate; //允许路由替换 },js代码
<button onclick="callFlutter()">callFlutter</button> function callFlutter(){ var url = "js://html?params1=111¶ms2=222" //url 为两端定义的协议 document.location = url; }四、Flutter 调用JS
在实际开发中免不了和js的数据交互,例如js需要拿到app登录的用户信息,这时候我们在Flutter端收到请求以后,可以通过拿到一个WebViewController,通过它的evaluateJavascript()方法,然后将我们的用户信息传递给js,具体代码如下:
Flutter 代码
onWebViewCreated: (WebViewController webViewController) { _controller = webViewController; }, JavascriptChannel _alertJavascriptChannel(BuildContext context) { return JavascriptChannel( name: 'MyApp', onMessageReceived: (JavascriptMessage message) { showToast(message.message); // js 告诉Flutter需要获取用户信息 if(message.messageType == "getUserInfo"){ //Flutter把用户信息传递到js var userInfo = User("username","token"); String userString = json.encode(userInfo); controller ?.evaluateJavascript('getUserInfo($userString)') ?.then((result) { }); } }); }js 代码
<button onclick="callFlutter()">获取用户信息</button> <script> function callFlutter() { // 我需要用户信息 var str = navigator.userAgent; if (str.includes('MyApp')) { // 此处为Flutter端JavascriptChannel定义的name MyApp.postMessage(JSON.stringify({ method: "getUserInfo" })); } else { $('body').html('<p>hello world</p>'); } } function getUserInfo(message) { var data = JSON.parse(JSON.stringify(message)) //注意此处json的解析方式 document.getElementById("p1").textContent = data.userUid; document.getElementById("p2").textContent = data.username; document.getElementById("p3").textContent = data.userType; document.getElementById("p4").textContent = data.realName; } </script>五、补充
在实际项目中,我们需要和js开发者定义交互的数据结构,例如:
class JsBridgeModel { int type; //类型 例如 打开微信、获取用户信息等 String message; var data; } JsBridgeModel(this.type,this.message,this.data); js端post发送消息的时候需要根据Flutter定义好的格式来 XX.postMessage(JSON.stringify({ type: 1,message:"",data:{} }))五、总结:
Flutter和js交互的方式基本就是这样,如果你还有需要补充的可以在下方留言。