简介
在挪动利用开发中,常常会遇到加载网页的需要,关上网页通常有两种形式,即在利用内应用内置的组件关上和应用零碎自带的浏览器关上。不过,在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: '加载本地文件'), ); }}
运行代码,成果下图所示。