• Flutter应用开发之webview_flutter插件


    简介

    在移动应用开发中,经常会遇到加载网页的需求,打开网页通常有两种方式,即在应用内使用内置的组件打开和使用系统自带的浏览器打开。不过,在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插件拉取到本地后,就可以使用它进行网页加载开发了。

    vi设计http://www.maiqicn.com 办公资源网站大全https://www.wode007.com

    基本使用

    如下所示,是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,
               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: '加载本地文件'),
        );
      }
    }
  • 相关阅读:
    【c++】龟兔赛跑问题
    【2016.3.21】关于字符串的一点总结
    程序员面试宝典(第五版)里的错误
    团队作业_总结_RTCSD2017
    团队作业_一周二周_RTCSD2017
    第三次作业_RTCSD2017
    第二次作业_RTCSD
    分析Demo1闪灯例程里的main.c
    第一次作业_RTCSD2017
    约束与自由
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/13705095.html
Copyright © 2020-2023  润新知