简介
在挪动利用开发中,常常会遇到加载网页的需要,关上网页通常有两种形式,即在利用内应用内置的组件关上和应用零碎自带的浏览器关上。不过,在 Flutter 利用开发中,因为官网并没有提供相似 Webview 的网页加载组件,所以如果我的项目中波及网页加载须要应用第三方插件库,如 webview_flutter、flutter_webview_plugin 等。
其中,webview_flutter 是 Flutter 官网开发和保护的网页加载插件库,而 flutter_webview_plugin 则是 Flutter 开源社区推出的网页加载插件。两个插件性能都差不多,都反对加载本地 html 文本、Flutter 调用 js 以及 js 调用 Flutter 等,然而我倡议应用官网推出的插件,因为它会继续的跟进已知的问题。
和其余 Flutter 插件的应用形式一样,应用 webview_flutter 之前须要先在 pubspec.yaml 文件中增加依赖脚本,如下所示。
dependencies:
webview_flutter: ^0.3.22+1
而后,咱们应用 flutter packages get 命令将 webview_flutter 插件拉取到本地后,就能够应用它进行网页加载开发了。
根本应用
如下所示,是 WebView 组件的构造函数。
WebView({
Key key,
this.onWebViewCreated, //WebView 创立实现之后的回调
this.initialUrl, // 初始化 URL
this.javascriptMode = JavascriptMode.disabled, //JS 执行模式,默认是不调用
this.javascriptChannels, // JS 能够调用 Flutter 的通道
this.navigationDelegate, // 路由委托,能够应用它执行拦挡操作
this.gestureRecognizers, // 手势相干
this.onPageStarted, // 开始加载页面回调
this.onPageFinished, // 页面加载实现的回调
this.onWebResourceError, // 资源加载失败回调
this.debuggingEnabled = false,
this.gestureNavigationEnabled = false,
this.userAgent,
this.initialMediaPlaybackPolicy =
AutoMediaPlaybackPolicy.require_user_action_for_all_media_types,
})
应用时,只须要依照参数传递对应的值即可。不过,在理论应用前,为了方便使用,咱们个别会对它进行二次封装,次要是界面和性能的封装。上面是我封装的一个能够加载本地和网络文件的 WebViewPage。
class WebViewPage extends StatefulWidget {
String url;
final String title;
final bool isLocalUrl;
WebViewController _webViewController;
WebViewPage({this.url, this.isLocalUrl = false, this.title});
@override
_WebViewPage createState() => _WebViewPage();
}
class _WebViewPage extends State<WebViewPage> {JavascriptChannel jsBridge(BuildContext context) => JavascriptChannel(
name: 'jsbridge', // 与 h5 端的统一 不然收不到音讯
onMessageReceived: (JavascriptMessage message) async{debugPrint(message.message);
});
@override
Widget build(BuildContext context) {
return Scaffold(appBar: _buildAppbar(),
body: _buildBody());
}
_buildAppbar() {
return AppBar(
elevation: 0,
backgroundColor: Color(0xccd0d7),
title: Text(widget.title, style: TextStyle(color: Colors.black),),
centerTitle: true,
leading: IconButton(icon: Icon(Icons.arrow_back, color: Color(0xFF23ADE5),), onPressed: () {})
);
}
_buildBody() {
return Column(
children: <Widget>[
SizedBox(
height: 1,
width: double.infinity,
child: const DecoratedBox(decoration: BoxDecoration(color: Color(0xFFEEEEEE))),
),
Expanded(
flex: 1,
child: WebView(initialUrl: widget.isLocalUrl ? Uri.dataFromString(widget.url, mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
.toString(): widget.url,
javascriptMode: JavascriptMode.unrestricted,
javascriptChannels: <JavascriptChannel>[jsBridge(context)
].toSet(),
onWebViewCreated: (WebViewController controller){
widget._webViewController = controller;
if(widget.isLocalUrl){_loadHtmlAssets(controller);
}else{controller.loadUrl(widget.url);
}
controller.canGoBack().then((value) => debugPrint(value.toString()));
controller.canGoForward().then((value) => debugPrint(value.toString()));
controller.currentUrl().then((value) => debugPrint(value));
},
onPageFinished: (String value){widget._webViewController.evaluateJavascript('document.title')
.then((title) => debugPrint(title));
},
),
)
],
);
}
// 加载本地文件
_loadHtmlAssets(WebViewController controller) async {String htmlPath = await rootBundle.loadString(widget.url);
controller.loadUrl(Uri.dataFromString(htmlPath,mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
.toString());
}
}
应用时,只须要依照传入对应的属性即可。须要阐明的是,加载本地 Html 文件时,须要在 pubspec.yaml 文件中申明这个 Html 文件,如下所示。
flutter:
// ...
assets:
- assets/real_data_help.html
而后,咱们应用封装的组件即可加载本地的 Html 文件。例如:
class MyApp extends StatelessWidget {
String localUrl = 'assets/real_data_help.html';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue,),
home:WebViewPage(url:localUrl, isLocalUrl: true, title: '加载本地文件'),
);
}
}
运行代码,成果下图所示。