Flutter 插件 webview_flutter 使用指北
现状
目前主流有两个插件,flutter_webview_plugin
和 webview_flutter
。
flutter_webview_plugin
是一个第三方插件,文档会比较全,star
数也最多。但是使用过程中有两个主要问题:
- 不能在JS中调用Flutter方法
- 不能在H5进入某个URL之前拦截
所以本文使用官方的 webview_flutter,目前还在预览版,期待更多的功能
安装插件
pubspec.yaml
dependencies
增加 webview_flutter: ^0.3.13
,有最新的使用最新版本,
dependencies:
webview_flutter: ^0.3.13
info.list
路径:ios/Runner/info.list
,添加配置:
<key>io.flutter.embedded_views_preview</key>
<string>YES</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
使用
参数一览
参数名 | 类型 | 默认值 | 说明 |
---|---|---|---|
initialUrl | String | '' | |
onWebViewCreated | Function | WebView创建完成时调用 | |
javascriptMode | JavascriptMode | JavascriptMode.disabled | JS执行模式 默认是不调用 |
javascriptChannels | Set | 使用javascriptChannel JS可以调用Flutter | |
navigationDelegate | Function | 拦截请求 | |
onPageFinished | Function | 页面加载完成调用 | |
gestureRecognizers | Set | 手势 |
场景
最简单的地加载一条url
WebView(
initialUrl: "https://flutterchina.club/",
//JS执行模式 是否允许JS执行
javascriptMode: JavascriptMode.unrestricted
)
h5 调用 flutter -- JavascriptChannel
// 往h5 window 里面插入全局方法 Toaster
JavascriptChannel _toastJavascriptChannel(BuildContext context) {
return JavascriptChannel(
name: 'Toaster',
onMessageReceived: (JavascriptMessage message) {
print(message);
Fluttertoast.showToast(
msg: message.message
);
});
}
// 往 Webview 组件注册 javascriptChannels
new WebView(
...
javascriptChannels: <JavascriptChannel>[ //javascriptChannels这个是api提供的互调的方法,
_toastJavascriptChannel(context),
].toSet()
)
// js 调用
Toaster.postMessage('js call flutter success!!')
h5 调用 flutter -- navigationDelegate
new WebView(
...
navigationDelegate: (NavigationRequest request) {
// print('navigationDelegate: ${request.url}');
if(request.url.indexOf('m=webview') > -1) {
String _url = helper.addUrlParam(request.url.replaceAll('&m=webview', ''));
Navigator.of(context).push(new MaterialPageRoute(builder: (_) {
return Browser(
title: ' ',
url: _url
);
}));
return NavigationDecision.prevent;
}
)
flutter 调用 h5
// 在页面加载完毕,修改 Webview 的标题
new WebView(
...
onPageFinished: (url) {
// 设置标题
_controller.evaluateJavascript("document.title").then((result){
print(result);
setState(() {
widget.title = result;
});
});
},
)
完整组件
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:fluttertoast/fluttertoast.dart';
import '../helper/index.dart' as helper;
class Browser extends StatefulWidget {
String url;
String title;
Browser({this.url, this.title});
@override
_BrowserState createState() => _BrowserState();
}
class _BrowserState extends State<Browser> {
dynamic _controller;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
JavascriptChannel _toastJavascriptChannel(BuildContext context) {
return JavascriptChannel(
name: 'Toaster',
onMessageReceived: (JavascriptMessage message) {
print(message);
Fluttertoast.showToast(
msg: message.message
);
});
}
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(
children: <Widget>[
new WebView(
initialUrl: widget.url,
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (controller) {
_controller = controller;
},
/**
* 当 url 带有 'm=webview',则打开新的webview
*/
navigationDelegate: (NavigationRequest request) {
// print('navigationDelegate: ${request.url}');
if(request.url.indexOf('m=webview') > -1) {
String _url = helper.addUrlParam(request.url.replaceAll('&m=webview', ''));
Navigator.of(context).push(new MaterialPageRoute(builder: (_) {
return Browser(
title: ' ',
url: _url
);
}));
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
onPageFinished: (url) {
// 设置标题
_controller.evaluateJavascript("document.title").then((result){
print(result);
setState(() {
widget.title = result;
});
});
// var a = '123';
// print(a+1);
// 测试flutter 调用我页面的方法
// _controller.evaluateJavascript("callJSFunc();").then((result){
// // print('callJSFunc has called: $result');
// });
},
javascriptChannels: <JavascriptChannel>[ //javascriptChannels这个是api提供的互调的方法,
_toastJavascriptChannel(context),
].toSet()
)
],
),
);
}
}
todo
- 接入cordova
- 获取设备的网络状态
参考文章
转载自:https://juejin.cn/post/6844903940820041735