最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Fluttter Webview与Vue结合的案例

    正文概述 掘金(wesin)   2021-05-03   1076

    Fluttter Webview与Vue结合的案例 tip: 用Flutter实现通用框架功能,然后把业务功能用Vue去实现,可以解决公司移动开发资源紧张,但是每个业务组都备有H5开发的场景。

    而H5开发又不需要管理麻烦的app上架,原生硬件调用等移动端知识。

    所以最近使用Flutter_inappwebview做了个app内置浏览器来实现这个功能。

    下面说下实现方案:

    引入Vue资源文件

    用webview直接打开网页显然是体验比较卡的,所以需要把Vue做好的页面build成资源文件,打包到Flutter工程里。

    pubspec.yaml配置文件引入资源文件。

      assets:
        - assets/
        - assets/fonts/
        - assets/css/
        - assets/home/
        - assets/js/
        - assets/test/
    

    如果这里我就引入了两个Vue的页面。一个test、一个home。

    准备Flutter_inappwebview

    Flutter_inappwebview官方案例里面用的例子使用的是最原始的方式,没有进度条, 随便页面状态发生变动都会重新rebuild webview。这显然不符合目前的Flutter开发理念。webview加载了网页后应该是固定而不需要重新build的。

    当时用的Flutter_bloc框架来解决,(最近发现GetX框架更简便,这里推荐下)这里很简单的在页面头部加了个进度条,中间来了个load动画。

    构建一个HPWebViewPage,核心代码

      InAppWebView webviewInit(BuildContext context) {
        HPWebViewBloc vbloc = BlocProvider.of<HPWebViewBloc>(context);
        print("view init: ${this.viewInfo.url}");
        return InAppWebView(
            key: const Key("in_app_webview"),
            initialUrlRequest: this.viewInfo.url.startsWith(HPWebViewConst.filePath)
                ? null
                : URLRequest(url: Uri.parse(this.viewInfo.url)),
            onWebViewCreated: (controller) {
              if (jsHandler != null) {
                jsHandler!(controller, context);
              }
            },
            onLoadStart: (controller, uri) =>
                vbloc.add(HPWebViewLoadStartEvent(controller, uri)),
            onLoadError: (controller, uri, code, message) =>
                vbloc.add(HPWebViewLoadErrorEvent(controller, uri, code, message)),
            onLoadHttpError: (controller, uri, code, message) =>
                vbloc.add(HPWebViewLoadErrorEvent(controller, uri, code, message)),
            onLoadStop: (controller, uri) =>
                vbloc.add(WebViewLoadStopEvent(controller, uri)),
            onProgressChanged: (controller, progress) =>
                vbloc.add(WebViewProgressEvent(controller, progress)),
            initialUserScripts: this.injectJSList);
      }
      
    

    jsHandler、injectJSList 是由外部传入的。Flutter与H5交互的代码。这个是由不同的业务定义。

    build 代码

      @override
      Widget build(BuildContext context) {
        return Stack(
          alignment: Alignment.center,
          fit: StackFit.expand,
          children: [
            webviewInit(context),
            Positioned(
                top: 0,
                child: BlocBuilder<HPWebViewBloc, HPWebViewState>(
                  builder: (context, state) {
                    print(state);
                    if (state is HPWebViewLoadStartState) {
                      return Container(
                          child: LinearProgressIndicator(value: 0), height: 2);
                    }
                    if (state is HPWebViewProgressState) {
                      return Container(
                          child:
                              LinearProgressIndicator(value: state.progress / 100),
                          height: 2);
                    }
                    return Container(height: 0, width: 0);
                  },
                ),
                left: 0,
                right: 0),
            Center(
              child: BlocBuilder<HPWebViewBloc, HPWebViewState>(
                builder: (context, state) {
                  if (state is HPWebViewLoadStartState ||
                      state is HPWebViewProgressState) {
                    return CircularProgressIndicator();
                  }
                  return Container(height: 0, width: 0);
                },
              ),
            )
          ],
        );
      }
    

    打开Webview

    打开webview需要注入交互的代码,不需要的话可以不加。

    class WebViewUtil {
      static void openWebView(WebViewModel viewInfo, BuildContext context) async {
        String injectJS = await rootBundle.loadString("assets/files/inject.js");
        Navigator.of(context).push(MaterialPageRoute(builder: (context) {
          return HPWebViewPage(
              viewInfo: viewInfo,
              injectJSList: UnmodifiableListView<UserScript>([
                UserScript(
                    source: injectJS,
                    injectionTime: UserScriptInjectionTime.AT_DOCUMENT_END),
              ]),
              jsHandler: _addJSHandler);
        }));
      }
    
      static void _addJSHandler(
          InAppWebViewController controller, BuildContext context) {
        controller.addJavaScriptHandler(
            handlerName: JSHandlerConst.close,
            callback: (_) {
              Navigator.of(context).pop();
            });
        controller.addJavaScriptHandler(
            handlerName: JSHandlerConst.openUrl,
            callback: (args) {
              var url = args[0]['url'];
              var title = args[0]['title'];
              var filterUrl = args[0]['filterurl'];
              var filterTitle = args[0]['filtertitle'];
              Navigator.of(context).pushNamed(HPWebViewPage.routeName,
                  arguments: WebViewModel(url,
                      title: title,
                      filterUrl: filterUrl,
                      filterTitle: filterTitle));
              // bloc.add(JSHandlerOpenUrlEvent(args));
            });
    
        controller.addJavaScriptHandler(
            handlerName: JSHandlerConst.back,
            callback: (args) {
              Navigator.of(context).pop();
            });
      }
    }	
    

    inject.js 只要是定义一套window.js.handler接口

    //侧滑返回
    handler.back = function() {
        window.flutter_inappwebview.callHandler('back');
    }
    

    目前的代码只能打开一个url,而不能打开本地的vue页面

    void _openWebPage(WebViewModel viewInfo, BuildContext context) {
        WebViewUtil.openWebView(viewInfo, context);
      }
     
     _openWebPage(
            WebViewModel("https://github.com/wesin/hp_webview",
                title: "github"),
            context);
     
    

    加载本地网页

    加载本地网页需要在app里启动一个代理服务,当通过代理加载url时,拦截请求。返回H5资源文件。通过这种方式,我们可以加载从服务端下载过来的html文件,也可以加载已经打包在工程的html文件。

    在main里启动本地代理服务,指定端口

    final HPWebViewProxy localhostServer = new HPWebViewProxy(port: 8765);
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await localhostServer.start();
      print(localhostServer.isRunning());
      
    

    如此就可以打开本地网页了

    ElevatedButton(
          onPressed: () => _openWebPage(
              WebViewModel("http://localhost:8765/home/"), context),
          child: Text("打开本地网页")),
     
    

    代理服务的代码和全部的代码都可以在我的github上看。 传送门


    起源地下载网 » Fluttter Webview与Vue结合的案例

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元