Flutter flutter_html插件加载html标签内容、 flutter_webview_plugin插件加载网页

纸上得来终觉浅,绝知此事要躬行。——陆游

 

自从Flutter官网发布第一版就开始接触了,中间有1年多没有接触,因为当初考虑这是新的技术框架,还是比较开好原生开发。时代变化的浪潮中,谁也无法预料未来谁会成为未来技术的主流,是语言还是莫某框架,有未可知。

最近着手用纯Flutter框架开发了一款 app,在开发的过程中也许遇到了和当年原生才出来的时候一样的坑,虽然坑不同,那也得去解决坑呀。当我们在技术的道路上着手解决了一系列问题,也许就是我们很自信的去和老板谈薪资的时候了。废话不多说了,我今天就遇到了两个问题:一个问题是Flutter编写的app在安卓和苹果机器上运行时加载htm标签内容需要显示加载的进度,第二个问题就是在两端机器上无法加载网页连接以http开头的网页。其实这两个问题都解决了,且听我慢慢道来。

先说第一个问题,其实第二个问题不是要说的重点,第二个问题我在搜索引擎中找到了答案,哈哈

实现后的效果:

                    

加载内容:<img src="http开头图片地址" alt="图片">

思路:

1、监听网页开始加载、加载中、加载完成

2、显示加载转圈提示

3、加载完成取消加载转圈提示

既然我们是使用的 flutter_html插件,为了能进一步实现我们想要的功能,首先得从插件源码进行粗略的观看了。

我们不难发现是继承自一个绘制的UI页的状态包括被渲染的内容都是始终不变的Widget 。

注意:有必要了解一下了解到了StatelessWidget和StatefullWidget的区别

class Html extends StatelessWidget {
  Html({
    Key key,
    @required this.data,
    this.padding,
    this.backgroundColor,
    this.defaultTextStyle,
    this.onLinkTap,
    this.renderNewlines = false,
    this.customRender,
    this.customEdgeInsets,
    this.customTextStyle,
    this.customTextAlign,
    this.blockSpacing = 14.0,
    this.useRichText = true,
    this.onImageError,
    this.linkStyle = const TextStyle(
        decoration: TextDecoration.underline,
        color: Colors.blueAccent,
        decorationColor: Colors.blueAccent),
    this.shrinkToFit = false,
    this.imageProperties,
    this.onImageTap,
    this.showImages = true,
  }) : super(key: key);

useRichText 表示是否使用富文本或者原始解析html方式,因为有图片和文本的加载我当选useRichText=true

通过解析html标签节点的方式去加载不同htm内容l标签,今天主要讲包含img标签的。

1、节点包括src、data:image、base64:

2、点击包括src、asset:

3、今天我遇到的也是要讲的,开头只是src :

 准备缓存图片:

node.attributes['src']表示获取到的图片地址,例如:<img src="http开头图片地址" alt="图片">

 precacheImage(
                    NetworkImage(node.attributes['src']),
                    buildContext,
                    onError: onImageError ?? (_, __) {},
                  );

Image.network()加载网络图片:

 frameBuilder 用于展示要加载的图片

loadingBuilder 用于展示图片加载开始到完成整过过程任意可表示加载进度的控件,此部分在flutter_html插件中没有,是我今天对此插件进行改装后的代码。

ImageChunkEvent loadingProgress表示加载的进度,表示没有加载或者加载完成,就不不需要展示加载的进度

表示加载的进度条,可自定义 
return Container(
                          width: ViewUtils.currentHeight(400.0),
                          height: ViewUtils.currentWidth(400.0),
                          alignment: Alignment.center,
                          child: NetLoadingDialog(
                            //requestCallBack: _register(),
                            outsideDismiss: false,
                          ),
                        );
 loadingBuilder: (BuildContext context, Widget child,
                          ImageChunkEvent loadingProgress) {
                        if (loadingProgress == null) return child;
                        return Container(
                          width: ViewUtils.currentHeight(400.0),
                          height: ViewUtils.currentWidth(400.0),
                          alignment: Alignment.center,
                          child: NetLoadingDialog(
                            //requestCallBack: _register(),
                            outsideDismiss: false,
                          ),
                        );
                      },
                    child: Image.network(
                      node.attributes['src'],
                      frameBuilder: (context, child, frame, _) {
                        if (node.attributes['alt'] != null && frame == null) {
                          return BlockText(
                            child: RichText(
                              textAlign: TextAlign.center,
                              text: TextSpan(
                                text: node.attributes['alt'],
                                style: nextContext.childStyle,
                              ),
                            ),
                            shrinkToFit: shrinkToFit,
                          );
                        }
                        if (frame != null) {
                          return child;
                        }
                        return Container();
                      },
                      loadingBuilder: (BuildContext context, Widget child,
                          ImageChunkEvent loadingProgress) {
                        if (loadingProgress == null) return child;
                        return Container(
                          width: ViewUtils.currentHeight(400.0),
                          height: ViewUtils.currentWidth(400.0),
                          alignment: Alignment.center,
                          child: NetLoadingDialog(
                            //requestCallBack: _register(),
                            outsideDismiss: false,
                          ),
                        );
                      },
                      width: (width ?? -1) > 0 ? width : null,
                      height: (height ?? -1) > 0 ? height : null,
                      scale: imageProperties?.scale ?? 1.0,
                      matchTextDirection:
                          imageProperties?.matchTextDirection ?? false,
                      centerSlice: imageProperties?.centerSlice,
                      filterQuality:
                          imageProperties?.filterQuality ?? FilterQuality.low,
                      alignment: imageProperties?.alignment ?? Alignment.center,
                      colorBlendMode: imageProperties?.colorBlendMode,
                      fit: imageProperties?.fit,
                      color: imageProperties?.color,
                      repeat: imageProperties?.repeat ?? ImageRepeat.noRepeat,
                      semanticLabel: imageProperties?.semanticLabel,
                      excludeFromSemantics:
                          (imageProperties?.semanticLabel == null)
                              ? true
                              : false,
                    ),
                    onTap: () {
                      if (onImageTap != null) {
                        onImageTap(node.attributes['src']);
                      }
                    },

最后使用了:

  child: Html(
                  useRichText: true,
                  data: _content,
                  defaultTextStyle: TextStyle(
                    fontSize: 18.0,
                    color: Colors.black,
                    decoration: TextDecoration.none,
                  ),
                ),

总结:加载带html标签的内容,我们需要知晓官方源码是通过解析标签根节点的方式去获取图片地址或者文本内容进行加载,其中的原理不是很复杂。

参考:

flutter_html插件:flutter_html | Flutter Package

StatelessWidget&StatefulWidgetFlutter Widget框架概述 - Flutter中文网

Image.net:Image.network constructor - Image class - widgets library - Dart API

资源下载:Flutter加载html标签源码.rar_flutterhtml标签,flutter加载html代码-其它文档类资源-CSDN下载

  • 95
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 39
    评论
要实现 Flutter WebView 页面自适应高度,可以使用 flutter_webview_plugin 件。该件提供了一个 onStateChanged 回调函数,可以监听 WebView 页面的状态改变。当页面完成后,可以获取 WebView 页面的高度,并将其应用到 WebView 上,从而实现自适应高度。 以下是一个简单的示例代码,演示如何实现 Flutter WebView 页面自适应高度: ```dart import 'package:flutter/material.dart'; import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'; class MyWebView extends StatefulWidget { final String url; MyWebView({required this.url}); @override _MyWebViewState createState() => _MyWebViewState(); } class _MyWebViewState extends State<MyWebView> { double webViewHeight = 100.0; @override Widget build(BuildContext context) { return Scaffold( body: Container( height: webViewHeight, child: WebviewScaffold( url: widget.url, withZoom: false, withJavascript: true, withLocalStorage: true, hidden: true, initialChild: Container( color: Colors.white, child: Center( child: CircularProgressIndicator(), ), ), appBar: AppBar( title: Text('WebView Demo'), ), onStateChanged: (state) { if (state.type == WebViewState.finishLoad) { setState(() { webViewHeight = double.parse(state.height.toString()); }); } }, ), ), ); } } ``` 在上面的代码中,我们定义了一个 MyWebView 类,使用 WebviewScaffold 来渲染 WebView 页面。在 onStateChanged 回调函数中,我们监听 WebView 页面的状态改变,并在页面完成后获取 WebView 的高度,并将其应用到 WebView 上。这样,就可以实现 WebView 页面的自适应高度了。
评论 39
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

️ 邪神

你自己看着办,你喜欢打赏我就赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值