草庐IT

Flutter 学习 之 封装 WebView

半城半离人 2023-03-28 原文

本文中用到的插件有
跳转外部浏览器插件 url_launcher
在App内部打开网页的插件 webview_flutter
在组件中加载Html片段的插件flutter_html

插件的引入

上面三个插件按需引入

  flutter_html: ^3.0.0-alpha.3
  webview_flutter: ^3.0.2
  url_launcher: ^6.1.0

需要实现的方法

加载在线网页

WebView(
                      initialUrl:  : _url,
                      //是否开启JS
                      javascriptMode: JavascriptMode.unrestricted,

                      ///WebView创建
                      onWebViewCreated: _onWebViewCreated,

                      ///页面开始加载
                      onPageStarted: _onPageStarted,

                      ///页面加载家属
                      onPageFinished: _onPageFinished,

                      ///如果出现错误
                      onWebResourceError: (WebResourceError error) =>
                          debugPrint('error:${error.description}'),
                    )),

  void _onWebViewCreated(WebViewController controller) async {
    webViewController = controller;
    _controller.complete(controller);
    webViewController!.clearCache();
  }

  void _onPageStarted(String url) {
    EasyLoading.show();
  }

  void _onPageFinished(String url) async {
    EasyLoading.dismiss();
  }

加载本地网页

加载本地网页的时候需要在WebViewCreated的时候调用方法来获取本地html文件

  _loadHtmlFromAssets() async {
    String fileHtmlContents = await rootBundle.loadString(_url);
    webViewController?.loadUrl(Uri.dataFromString(fileHtmlContents,
            mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
        .toString());
  }

加载本地html片段

这里使用的是HTML插件 封装起来非常的简单

class HtmlRichText extends StatelessWidget {
  final String richText;
  final Map<String, Style>? style;

  const HtmlRichText({Key? key, this.richText = "内容为空", this.style})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        Html(
          data: richText,
          style: style ?? {},
        )
      ],
    );
  }
}

使用

onJumpTo 这个是你之前定义路由器的时候跳转方法 这里需要你自己去实现
加载网络地址

      onJumpTo(name: RouterName.webViewPage, arguments: <String, dynamic>{
        "title": "百度一下,
        "url": "https://www.baidu.com",
        "isLocalUrl": false,
      });

加载 本地地址

      onJumpTo(name: RouterName.webViewPage, arguments: <String, dynamic>{
        "title": "我自己的文件,
/// 你自己存储的文件路径 这个路径还需要在 pubspec.yaml中注册
        "url": "assets/html/html.html",
        "isLocalUrl": true,
      });

加载代码段

  onJumpTo(name: RouterName.webViewPage, arguments: <String, dynamic>{
        "title": "一个代码片段,
        "url": "",//代码段的时候网址置为空
        "isLocalUrl": true,//本地是true
        "richText": ''' <br/>3、用户不得利用“一个Demo”账号或本服务制作、上载、复制、发布、传播如下干扰“服务”正常运营,以及侵犯其他用户或第三方合法权益的内容:
            <br/>(1) 含有任何性或性暗示的; <br/>(2) 含有辱骂、恐吓、威胁内容的; <br/>(3) 含有骚扰、垃圾广告、恶意信息、诱骗信息的; <br/>(4)
            涉及他人隐私、个人信息或资料的; <br/>(5) 侵害他人名誉权、肖像权、知识产权、商业秘密等合法权利的; <br/>(6)
            含有其他干扰本服务正常运营和侵犯其他用户或第三方合法权益内容的信息。 <br/>&nbsp;<br/>''' //一段文字用三个引号控制
      }

完整代码

class WebViewPage extends StatefulWidget {
  final Map<String, dynamic>? arguments;

  const WebViewPage({Key? key, this.arguments}) : super(key: key);

  @override
  State<WebViewPage> createState() => _WebViewPageState();
}

class _WebViewPageState extends State<WebViewPage> {
  WebViewController? webViewController;
  final Completer<WebViewController> _controller =
      Completer<WebViewController>();
  String _title = "";
  String _url = "";
  String _richText = "";
  bool _isLocalUrl = false;
  bool _isShowAppBar = true;

  @override
  void initState() {
    super.initState();
    _title = StringUtil.isNotEmpty(widget.arguments?["title"])
        ? widget.arguments!["title"]
        : "";
    _url = StringUtil.isNotEmpty(widget.arguments?["url"])
        ? widget.arguments!["url"]
        : "";
    _richText = StringUtil.isNotEmpty(widget.arguments?["richText"])
        ? widget.arguments!["richText"]
        : "";
    _isLocalUrl = widget.arguments?["isLocalUrl"] ?? false;
    _isShowAppBar = widget.arguments?["isShowAppBar"] ?? true;
  }

  @override
  void dispose() {
    EasyLoading.dismiss();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar:
          _isShowAppBar ? ComAppBar.buildNormal(center: Text(_title)) : null,
      body: WillPopScope(
          onWillPop: () async {
            goBack();
            return false;
          },
          child: ((StringUtil.isEmpty(_url) && !_isLocalUrl) ||
                  (_isLocalUrl &&
                      (StringUtil.isEmpty(_richText) &&
                          StringUtil.isEmpty(_url))))
              ? Container(
                  padding: EdgeInsets.all(ScreenHelper.width(18)),
                  child: const Center(
                    child: Text("当前路径为空"),
                  ),
                )
              : _isLocalUrl && StringUtil.isNotEmpty(_richText)
                  ? HtmlRichText(
                      richText: _richText,
                    )
                  : WebView(
                      initialUrl: _isLocalUrl ? "" : _url,
                      //是否开启JS
                      javascriptMode: JavascriptMode.unrestricted,

                      ///WebView创建
                      onWebViewCreated: _onWebViewCreated,

                      ///页面开始加载
                      onPageStarted: _onPageStarted,

                      ///页面加载家属
                      onPageFinished: _onPageFinished,

                      ///如果出现错误
                      onWebResourceError: (WebResourceError error) =>
                          debugPrint('error:${error.description}'),
                    )),
    );
  }

  goBack() async {
    if (webViewController == null) {
      NavigatorUtil().pop();
      return;
    }
    bool goBack = await webViewController!.canGoBack();
    if (goBack) {
      webViewController!.goBack();
    } else {
      NavigatorUtil().pop();
    }
  }

  void _onWebViewCreated(WebViewController controller) async {
    webViewController = controller;
    if (_isLocalUrl) {
      await _loadHtmlFromAssets();
    }
    _controller.complete(controller);
    webViewController!.clearCache();
  }

  void _onPageStarted(String url) {
    EasyLoading.show();
  }

  void _onPageFinished(String url) async {
    if (_isLocalUrl) {
      //加载js文件
      // String jsContent = await rootBundle.loadString(jsPath);
      // webViewController?.runJavascript(jsContent);
      //加载js脚本 _webViewController.runJavascriptReturningResult("setname('hsw')").then((value) => {
      // print(value)
    }
    EasyLoading.dismiss();
  }

  _loadHtmlFromAssets() async {
    String fileHtmlContents = await rootBundle.loadString(_url);
    webViewController?.loadUrl(Uri.dataFromString(fileHtmlContents,
            mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
        .toString());
  }
}

有关Flutter 学习 之 封装 WebView的更多相关文章

  1. ruby-on-rails - 如何在 Ruby 中封装包含的模块方法? - 2

    我希望能够在包含该模块的类无法访问的模块中拥有方法。给定以下示例:classFooincludeBardefdo_stuffcommon_method_nameendendmoduleBardefdo_stuffcommon_method_nameendprivatedefcommon_method_name#blahblahendend我希望Foo.new.do_stuff爆炸,因为它试图访问模块试图对其隐藏的方法。不过,在上面的代码中,Foo.new.do_stuff可以正常工作:(有没有办法在Ruby中实现我想做的事情?更新-真正的代码classPlace"Place"}has_

  2. Flutter 环境变量配置和flutter doctor中的错误解决 - 2

    一、环境变量右键点击我的电脑-属性:然后找到环境变量 1.Android的SDK不在C盘的话需要额外配这个到用户环境变量:ANDROID_HOMED:\AndroidSDK2.然后在系统变量:Path中添加一条这样的值        D:\Flutter\flutter\bin             这个值写flutter包解压的实际地址即可 3.在系统变量中添加两个镜像变量:        变量名:FLUTTER_STORAGE_BASE_URL      变量值:https://storage.flutter-io.cn        变量名:PUB_HOSTED_URL      变量

  3. ruby - 如何在 Ruby Gem 中封装 Ruby C 扩展? - 2

    我找不到很多这方面的文档。如何打包gem,以便在安装gem时编译C扩展?特别是我想这样做:在Linux和MacOSX上,我想在安装gem时编译C扩展在Windows上,我想简单地安装一个预编译的.so对此的任何帮助,特别是示例源代码,都将非常有用:) 最佳答案 LuisLavena创造了rake-compiler只是为了这个目的。Homepage/GitHubGitHubWiki但是,您确定需要C扩展吗?关于C扩展的事情是,每个Ruby实现都有自己的C扩展API(而非基于C的API,如XRuby、JRuby、Ruby.NET、Iro

  4. ruby - Ruby 的 "Open Classes"会破坏封装吗? - 2

    在Ruby中,程序员可以更改预定义的类。所以一个非常糟糕的程序员可能会做这样的事情:classStringdef==(other)returntrueendend显然,几乎没有人会这么蠢,但是对预定义类进行更细微的更改可能会导致已经运行的代码出现问题的想法在我看来违反了封装原则。四个问题:首先,这是否实际上违反了面向对象的封装原则?其次,作为一名程序员,有没有一种方法可以保证我正在使用类的未修改版本的代码?第三,我应该在我的代码中“打开”类吗?原因?最后,在大规模生产编码环境中如何处理这类事情?换句话说,编程行业的人真的用其他人的代码来做这件事吗?将使用?或者即使他们不这样做,你如何确

  5. 微信小程序 webview页面分享弹窗 - 2

    微信小程序webview中使用cover-view展示分享弹窗公司业务需要在webview中添加分享弹窗,可以发送给朋友及生成海报分享,因为好几个详情都需要这个功能,因此抽离了share-sheet的组件,ui效果如下图:点击分享,显示以下弹窗share-sheet.wxml如下:{!show}}"catchtouchmove="poptouchmove">发送给朋友生成海报取消share-sheet.js如下:Component({options:{addGlobalClass:true,},/***组件的属性列表*/properties:{//控制弹窗显示与否show:{type:Bool

  6. 嵌入式学习之QT学习----3 制作简单的QT界面(如:QQ登录界面) - 2

    1、创建一个QT工程newproject—>Application—>QtWidgetsApplication—>choose…(注意不要有中文路径)填写名称(我写的名称为class2)和创建路径(D:\qt\qt_demo\class2)—>填写类名,这里基类要选择“QWidget”,这样一个QT工程就创建好啦。qt的移植性非常强,一套代码我们不用修改太多,直接通用所有的平台。说明:QMainWindow:主窗口类,主窗口具有主菜单栏、工具栏和状态栏,类似于一般的应用程序的主窗口。QWidget:它是所有具有可视界面的基类,选择QWidget创建的界面对各种界面组件都可以支持。QDialog

  7. javascript - 从 atom Electron 中的 webview 访问 DOM - 2

    是否可以从原子Electron桌面开发工具包中的webview元素中抓取html,我正在尝试访问DOM但我什么也没得到,我在运行时尝试了控制台中的document.links但我得到了空属性和对象作为返回?window.onresize=doLayout;varisLoading=false;onload=function(){varwebview=document.querySelector('webview');doLayout();vart=webview.executeJavaScript("console.log(document.links);");document.que

  8. java - 从 JavaFX 程序为 WebView 执行 Javascript 函数 - 2

    我正在尝试从Java程序执行Javascript函数。Javascript函数获取HTML文件的内容并突出显示特定单词的出现。是否可以从webview对象调用Javascript函数? 最佳答案 要在WebView中运行javascript,您可以使用WebEngine.executeScript()方法。并且有很多方法可以通过javascript突出显示文本。例如。HighlightwordinHTMLtext(butnotmarkup)一起:WebViewwebView=newWebView();finalWebEngineen

  9. javascript - 在 WebView 源代码中执行 JavaScript - 2

    有人知道如何(如果可能的话)在ReactNative的WebView“内部”执行JS吗?场景:我的WebView中显示了这个远程登录页面(网站),该网站有一系列与用户事件相对应的事件。所有事件都触发一个回调,WebView必须监听(这不是问题)。在每个回调中都有一个对JavaScript函数的引用,它必须在WebView内部调用(这就是问题所在!)。因此,我需要从我的ReactNative应用程序调用这个JavaScript函数,该函数位于我的WebView中加载的网站页面(源)上。我有什么:我用onShouldStartLoadWithRequest监听回调并以此操作WebView的

  10. javascript - 如何封装mocha `expect()`代码? - 2

    我正在尝试测试是否存在一些我希望在所有测试中都需要的api响应属性(status和data属性)。这是一个通用测试,它断言supertest中的所需属性expect()方法:it('shouldcreateawidget',done=>{letstatus=200;request(test_url).post('/api/widgets').set('Authorization',`Bearer${token}`).send({sku:my_widget_data.sku,name:my_widget_data.name,description:''}).expect(res=>{as

随机推荐