Flutter應用開發之webview_flutter插件

簡介

在移動應用開發中,常常會遇到加載網頁的需求,打開網頁一般有兩種方式,即在應用內使用內置的組件打開和使用系統自帶的瀏覽器打開。不過,在Flutter應用開發中,因爲官方並無提供相似Webview的網頁加載組件,因此若是項目中涉及網頁加載須要使用第三方插件庫,如webview_flutter、flutter_webview_plugin等。javascript

其中,webview_flutter是Flutter官方開發和維護的網頁加載插件庫,而flutter_webview_plugin則是Flutter開源社區推出的網頁加載插件。兩個插件功能都差很少,都支持加載本地html文本、Flutter調用js以及js調用Flutter等,可是我建議使用官方推出的插件,由於它會持續的跟進已知的問題。html

和其餘Flutter插件的使用方式同樣,使用webview_flutter以前須要先在pubspec.yaml文件中添加依賴腳本,以下所示。java

dependencies:
   webview_flutter: ^0.3.22+1

而後,咱們使用flutter packages get命令將webview_flutter插件拉取到本地後,就可使用它進行網頁加載開發了。web

基本使用

以下所示,是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文件,以下所示。app

flutter:
 //  ...
  assets:
   - assets/real_data_help.html

而後,咱們使用封裝的組件便可加載本地的Html文件。例如:less

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: '加載本地文件'),
    );
  }
}

運行代碼,效果下圖所示。
在這裏插入圖片描述async

相關文章
相關標籤/搜索