一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
- 在App中我们避免不了部分动态页面使用web形式的进行展示,但是Flutter并不像原生那样有现成的webView控件来给我们使用,这时候就需要一个官方维护的第三方的插件
webview_flutter: ^2.8.0来进行展示,截止目前官方已更新至3.0.2,当然社区也有其他web的插件,选择这个是因为他是google官方维护的,所以不用担心停止维护而出现一些问题。
加载web页面
- 构造方法
const WebView({
Key? key,
this.onWebViewCreated,// webview创建完毕回调
this.initialUrl,//加载的url
this.javascriptMode = JavascriptMode.disabled,//js执行模式 默认不执行js
this.javascriptChannels,//与js通信方法
this.navigationDelegate,//路由委托 可执行拦截url操作
this.gestureRecognizers,//执行手势操作相关
this.onPageStarted,//页面开始加载回调
this.onPageFinished,//页面加载完毕回调 可在此回调设置web title
this.onProgress,//加载进度
this.onWebResourceError,//web加载失败回调
this.debuggingEnabled = false,//是否启用调试模式 默认不启用
this.gestureNavigationEnabled = false,//指示水平滑动手势是否会触发前向列表导航 这个只在iOS生效
this.userAgent,//设置用户代理 iOS 9之前不支持
this.zoomEnabled = true,//是否支持缩放 iOS需要设置支持js调用
this.initialMediaPlaybackPolicy =
AutoMediaPlaybackPolicy.require_user_action_for_all_media_types,//web中媒体是否自动播放 有两个枚举值
this.allowsInlineMediaPlayback = false,//是否允许在iOS上在线播放HTML5视频,Android默认允许
this.backgroundColor,//设置背景色 默认透明
一般我们都会写一个通用的web页面来加载,上面方法按需求引入即可,需要注意的是有部分字段是在iOS上需要特殊处理,比如如果需要支持缩放模式,iOS上必须要设置javascriptMode = JavascriptMode.unrestricted;支持js调用才行。
与Web通信
- 上面我们看到有一个参数是与js通信的相关方法
javascriptChannels,接下来我们就看看这个方法怎么和web进行通信的。进行两种情况说明: 1、Flutter如何调用Js的方法并获取返回值。
首先在构造函数onWebViewCreated(controller)回调中我们获取webView控制器,使用它我们可以获取title等关键信息的值并可以掉用js中的方法。
onWebViewCreated: (controller) {
_webViewController = controller;
},
然后在我们需要调用js的地方掉用下面方法返回一个Future<String>结果。比如js中有一个hello方法,接受一个参数,返回一个json串,我们就可以用下方这个方法来掉用js中的方法。
await _webViewController?.runJavascriptReturningResult("window.hello('params')");
当然如果不需要返回值直接调用下面第二个方法就行。
2、Web中如何调用Flutter中的方法。
还是在构造函数中我们可以看到有个javascriptChannels方法,web调用flutter方法就在这里进行,我们看到javascriptChannels是一个 Set<JavascriptChannel> 集合,也就是说每一个
JavascriptChannel就代表一个js访问flutter的通道,我们可以在这里定义我们的flutter方法。
final Set<JavascriptChannel>? javascriptChannels;
具体使用:JavascriptChannel构造一共有以下两个字段。
JavascriptChannel(
name: "方法名",//务必跟js端一样才行
onMessageReceived: (JavascriptMessage message) {
// message.message;是js向我们传递的参数 我们就可以根据参数来执行我们的逻辑。
}),
具体用法:通过调用 postMessage 方法传递参数,
// name跟flutter保持一致 调用postMessage方法传递参数。
name.postMessage('Hello FLutter');
查了下资料,这里如果js端想要返回结果是无法直接返回的,因为这个方法的返回时 void,所以如果js端需要返回值,就需要我们在回调中主动调用js发送消息了。
总结
在Fluter中加载WebView还是需要依赖原生WebView引擎来进行渲染,可见Flutter对于WebView并没有自己渲染引擎,根据不同的平台来调用不同的Web引擎来进行渲染,与js互相通信的设计来说使用还是非常方便的,突然有个问题: 目前Flutter支持Web开发,虽然还不完善,如果Flutter应用镶嵌的Web页面也是Flutter开发的,这样的话还掉用原声渲染引擎的话是不是就多此一举了?还是Flutter以后会针对web出一个自己的渲染引擎?