Flutter中的Image入门讲解

栏目: Android · 发布时间: 5年前

内容简介:图片常用的格式主要有图片加载到内存中的时候,假如是压缩格式则会解压缩,并占用上图中memory中所占用的内存。本文的一些内容会涉及到这些简单的知识,有兴趣的同学可以上网寻找更多资料。安卓开发者应该都知道Android中并不是天生支持gif和webp动图,但是这一特性在flutter中被很好的支持了。放一张官方的图:

图片常用的格式主要有 bmp,jpg,png,gif,web 等。图片也是一种二进制文件,每种格式的图片都由固定的头信息和真实数据块组成。图片原始数据一般从2byte-4byte。

type bits memory
ARGB_8888 32 4*W*H
ARGB_4444 16 2*W*H
RGB_565 16 2*W*H
ALPHA_8 8 1*W*H

图片加载到内存中的时候,假如是压缩格式则会解压缩,并占用上图中memory中所占用的内存。本文的一些内容会涉及到这些简单的知识,有兴趣的同学可以上网寻找更多资料。

安卓开发者应该都知道Android中并不是天生支持gif和webp动图,但是这一特性在flutter中被很好的支持了。放一张官方的图:

Flutter中的Image入门讲解

flutter的图像处理是在engine中完成的,但是这个引擎提供的接口都是最基本的图片信息,如何根据设定的属性展示到屏幕上是在flutter中完成的。

在engine中的 ./lib/ui/painting/codec.cc 文件中展示了调用dart代码的资源:

static sk_sp<SkImage> DecodeImage(fml::WeakPtr<GrContext> context,
                                  sk_sp<SkData> buffer,
                                  size_t trace_id)
复制代码

这个方法用于生成一个SkImage,并将主要属性映射到flutter中的 ui.Image 类中。这个ui.Image就是可以直接通过canvas渲染到屏幕上的数据了。

常见控件

flutter提供了丰富的控件库,但是我们首先要搞清楚一个原理,所有的widget并不是直接绘制图片的,而是控制的图片的主要属性的容器,负责绘制的是RenderObject,他们中间是通过ElementTree来联系起来。有了这个基础后,所有的widget都不会提供画布(canvas)来直接绘制image,所以在任何一个Widget源码中都不会提供绘制的代码。来看一下主要的Widget:

1. RawImage

这是一个最基础图片容器Widget。它能直接将原始图片呈现到屏幕上,并且有一些列的属性可供操作:

const RawImage({
    Key key,
    this.image,
    this.width,
    this.height,
    this.scale = 1.0,
    this.color,
    this.colorBlendMode,
    this.fit,
    this.alignment = Alignment.center,
    this.repeat = ImageRepeat.noRepeat,
    this.centerSlice,
    this.matchTextDirection = false,
    this.invertColors = false,
    this.filterQuality = FilterQuality.low,
  }) : assert(scale != null),
       assert(alignment != null),
       assert(repeat != null),
       assert(matchTextDirection != null),
       super(key: key);
复制代码

其中image类型就是上边提到的 ui.Image ,这个数据的获取官方推荐通过ImageStream添加listener来获取。

  • color和colorBlendMode

这两个属性可以做出许多的效果。

Flutter中的Image入门讲解

看一段简单的代码

class _MyHomePageState extends State<MyHomePage> {
  ImageInfo info;//图片信息
  List<BlendMode> blendModes = BlendMode.values;//所有的混合模式转换为list

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    Image.asset("images/yuan.png")
        .image
        .resolve(createLocalImageConfiguration(context))
        .addListener((ImageInfo image, bool synchronousCall) {
      setState(() {
        info = image; //刷新状态
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GridView.builder(
        itemCount: blendModes.length - 1,
        padding: EdgeInsets.only(top: 10.0),
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 4,
        ),
        itemBuilder: getItemBuilder,
      ),
    );
  }

  Widget getItemBuilder(BuildContext context, int index) {
    return Column(
      children: <Widget>[
        RawImage(
          image: info?.image,
          color: Colors.red,
          width: 40,
          height: 40,
          colorBlendMode: blendModes[index + 1],
          fit: BoxFit.cover,
        ),
        Container(
          padding: EdgeInsets.only(top: 10.0),
          child: Text(
            blendModes[index + 1].toString().split("\.")[1],
            style: TextStyle(
              color: Colors.black,
              fontSize: 15.0,
            ),
          ),
        ),
      ],
    );
  }
}
复制代码

flutter中的混合模式是枚举类型,和Android中的图片混合模式画笔混合模式基本保持一致。上面的代码描述了所有的混合模式并配有图,除了clear没有在里边(clear模式会清除所有内容)。image是一个简单的图片,带透明通道的绿色的圆,在图中就是dst模式下的样子,背景是一个纯红色,在图中就是src模式下的样子。

  • fit属性使用的是Boxfit的枚举值,看一下效果:

  • fill

填充,忽略原有的宽高比,填满为止

Flutter中的Image入门讲解
  • contain

包含,不改变原有比例让容器包含整个图片,容器多余部分填充背景

Flutter中的Image入门讲解
  • cover

覆盖,不改变原有比例,让图片充满整个容器,图片多余部分裁剪 ///

Flutter中的Image入门讲解
  • fitWidth

横向图片填充

Flutter中的Image入门讲解
  • fitHeight

纵向图片填充

Flutter中的Image入门讲解
  • none

原始大小居中

Flutter中的Image入门讲解
  • scaleDown

图片大小小于容器事相当于none,图片大小大于容器时缩小图片大小实现contain

Flutter中的Image入门讲解

centerSlice属性专门用于nine-patch文件。

其他属性暂时不讲。

一般情况下这个控件很少使用,但是他是其他Image控件的实现基础,所以必须要拎出来讲一下。

Image

这是一个通用包装类,它包装了RawImage,同时提供了一些简便的 Named constructors 来使用AssetsImage,ExactAssetImage等ImageProvider的子类。

  • Image , 从ImageProvider来获取图片显示

这个类的使用基本和RawImage一致,在使用的时候只是将参数 ui.Image 包装为了 ImageProvider ,不用再自己监听ImageStream。典型简单用法:

Widget image = Image(AssetImage("images/yuan.png"))
复制代码
  • Image.asset , 从Asset资源中获取图片显示

这个方法是 ImageProviderAssetImage 的简单用法:

Widget image = Image.asset("images/yuan.png")
复制代码
  • Image.network , 从URL获取网络图片显示

这个方法是 ImageProviderNetworkImage 的简单用法:

Widget image = Image.network("http://img.rangaofei.cn/01b18.jpg")
复制代码
  • Image.file , 从文件中获取图片显示

这个方法是 ImageProviderFileImage 的简单用法:

Widget image = Image.file(file)
复制代码
  • Image.memory 从内存中获取图片显示.

这个方法是 ImageProviderMemoryImage 的简单用法:

Widget image = Image.memory(byteList)
复制代码

CircleAvatar

主要用来显示用户的头像,任何图片都会被剪切为圆形。

一个简单用法:

CircleAvatar(
          child: Text("头像"),
          backgroundImage: AssetImage("images/yuan.png"),
          backgroundColor: Colors.red,
          radius: 50.0,
        ),
复制代码

生成的图像如下:

Flutter中的Image入门讲解

CircleAvatar 内置了许多的功能。randius用来控制图片的大小,同时它可以自动感知当前theme是白天模式还是夜间模式来切换图片颜色,另外它实际是包装了 AnimatedContainer ,设置的动画时间是200ms。在改变它的一些相关属性时会自动使用动画来执行。看一个简单的动图:

Flutter中的Image入门讲解

代码如下:

class _MyHomePageState extends State<MyHomePage> {
  double radius = 10.0;

  @override
  void initState() {
    super.initState();
    Future<Duration>.delayed(Duration(milliseconds: 2 * 1000), () {
      setState(() {
        radius = 20.0;
      });
      return Duration(milliseconds: 210);
    }).then((Duration d) {
      Future<Duration>.delayed(d, () {
        setState(() {
          radius = 40.0;
        });
        return Duration(milliseconds: 210);
      }).then((Duration d) {
        Future<Duration>.delayed(d, () {
          setState(() {
            radius = 30.0;
          });
        });
      });
      ;
    });
  }

  @override
  Widget build(BuildContext context) {
   
    return Scaffold(
      body: Center(
        child: CircleAvatar(
          child: Text("头像"),
          backgroundImage: AssetImage("images/yuan.png"),
          radius: radius,
        ),
      ),
    );
  }
}
复制代码

这里我并没有使用AnimationController来控制radius值的变化,而是通过一个延时来控制。初始化的时候radius是10.0,延迟两秒后变为20.0,因为CircleAvatar默认的过度时间是200ms,为了有一个平滑的国度效果,我把下一次改变时间设置为了210ms,这时半径是40.0,最后经过210ms后半径设置为30.0,整个变化过程为:

10->20->40->30
复制代码

DecorationImage

主要用于 BoxDecoration 中的image属性,可以讲图片展示为boxdecoration。这里不做详细解释。

Widget getBoxImage() {
    return Container(
      decoration: BoxDecoration(
          image: DecorationImage(image: AssetImage("images/yuan.png"))),
    );
  }
复制代码

这个并不是一个Widget,只能用在BoxDecoration

Ink.image

同样很简单,用于显示一张图片。 这里相当于Ink一个简单写法,这个Ink控件里边只有decoration.image属性的话,可以直接替代Ink。

Widget getInkedImage() {
    return Ink.image(image: AssetImage("images/timg.jpeg"));
  }
复制代码

ImageIcon

基本和上边的一致效果:

Widget getImageIcon() {
    return ImageIcon(AssetImage("images/timg.jpeg"));
  }
复制代码

FadeInImage

占位图渐变动画控件,这个控件在加载网络图片时经常用到。主要作用是在加载网络图片这个耗时操作时显示一个占位图,并在获取到网络图片时以alpha动画来做出一个淡入淡出的效果。

看一下效果图

Flutter中的Image入门讲解

但是这个并不是一个银弹,在加载单帧图片时确实可以达到很好的效果,但是在加载网络图片时会丢失显示plcaceholder淡出时的所有帧,同样在网络图片错误时并不会有错误的占位图,而是直接抛出异常。这里不详细解释了。

Image的加载过程

上边介绍了一些基本的Image控件,这些都是属于Widget层使用的,但是他们的主要依赖都是 ImageProvider ,我们可以通过订制 ImageProvider 来实现自己的加载方式。

具体流程如图

Flutter中的Image入门讲解

在解析出来的ImageInfo中可以通过 Future<ByteData> toByteData({ImageByteFormat format: ImageByteFormat.rawRgba}) 方法改变ImageByte的数据格式:

  1. rawRgba,未解码的byte,每个通道占8bit
  2. rawUnmodified,未解码且为修改的byte,例如灰度图
  3. png,最常见的无损数据格式

这里有我做的一个控件来控制gif的加载速度:

Flutter中的Image入门讲解

最后附上源码:

github.com/rangaofei/s…

初学者,还有我做的一个简单的包:

pub.flutter-io.cn/packages/sa…


以上所述就是小编给大家介绍的《Flutter中的Image入门讲解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

标签: flutter image

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编写高质量代码:改善Python程序的91个建议

编写高质量代码:改善Python程序的91个建议

张颖、赖勇浩 / 机械工业出版社 / 2014-6 / 59.00元

在通往“Python技术殿堂”的路上,本书将为你编写健壮、优雅、高质量的Python代码提供切实帮助!内容全部由Python编码的最佳实践组成,从基本原则、惯用法、语法、库、设计模式、内部机制、开发工具和性能优化8个方面深入探讨了编写高质量Python代码的技巧与禁忌,一共总结出91条宝贵的建议。每条建议对应Python程序员可能会遇到的一个问题。本书不仅以建议的方式从正反两方面给出了被实践证明为......一起来看看 《编写高质量代码:改善Python程序的91个建议》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具