Flutter Widgets: Image

11,879 阅读3分钟
原文链接: blog.csdn.net

介绍

Image, 图片显示Widget, 和Android ImageView相似,但是从实际使用的方法上看,与常用的图片加载库,如Picasso,Glide等相似,支持本地图片,资源图片,网络图片等加载方式。

类结构

这里写图片描述

构造方法

方式 解释
Image() 通用方法,使用ImageProvider实现,如下方法本质上也是使用的这个方法
Image.asset 加载资源图片
Image.file 加载本地图片文件
Image.network 加载网络图片
Image.memory 加载Uint8List资源图片

属性值

image

ImageProvider, 抽象类,需要自己实现获取图片数据的操作。如下是常用的一些ImageProvider,当然自定义自己的ImageProvider也是OK的,实现方法,可以参考下面表中这些已经成熟使用的例子。

ImageProvider
ExactAssetImage
AssetImage
NetworkImage
FileImage
MemoryImage
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
      appBar: new AppBar(title: new Text("Container Test"),
        centerTitle: true,),

      body: new ListView(
        children: <Widget>[
          // 资源图片
          new Image.asset('imgs/logo.jpeg'),
          //网络图片
          new Image.network(
              'https://flutter.io/images/homepage/header-illustration.png'),
          // 本地文件图片
          new Image.file(new File("/Users/gs/Downloads/1.jpeg")),
          // Uint8List图片
          new Image.memory(bytes),
          //使用ImageProvider加载图片
          new Image(image: new NetworkImage(
              "https://flutter.io/images/homepage/screenshot-2.png"),)
        ],
      ),
    );
  }

这里写图片描述

width & height

Image显示区域的宽度和高度设置,这里需要把Image和图片两个东西区分开,图片本身有大小,Image Widget本身也是有大小的,Image Widget是图片的容器。宽度和高度的配置经常和下面的fit属性配合使用。

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    Image image = new Image.asset(
      'imgs/logo.jpeg',
      width: 200.0,
      height: 100.0,
      fit: BoxFit.fill,
    );

    return new Scaffold(
      appBar: new AppBar(title: new Text("Image Test"),
        centerTitle: true,),
      body: image,
    );
  }

设置宽度高度,然后设置图片充满Image,因为我们的源图片是1:1的大小,所以这里拉伸或者挤压是正常。
这里写图片描述

fit

fit Description Result
BoxFit.fill 全图显示,显示可能拉伸,充满
BoxFit.contain 全图显示,显示原比例,不需充满
BoxFit.cover 显示可能拉伸,可能裁剪,充满
BoxFit.fitWidth 显示可能拉伸,可能裁剪,宽度充满
BoxFit.fitHeight 显示可能拉伸,可能裁剪,高度充满
BoxFit.none
BoxFit.scaleDown 效果和contain差不多,但是此属性不允许显示超过源图片大小,可小不可大

color & colorBlendMode

color和colorBlendMode一般配合使用,BlendMode, 为混合模式的意思,包含如下诸多模式。感觉和Android中Xfermode是一个原理。
这里写图片描述
随意看几个效果吧。

BlendMode.colorBurn

    Image image = new Image.asset(
      'imgs/logo.jpeg',
      width: 400.0,
      height: 500.0,
      fit: BoxFit.scaleDown,
      color: Colors.greenAccent,
      colorBlendMode: BlendMode.colorBurn,
    );

这里写图片描述

BlendMode.exclusion

这里写图片描述

BlendMode.colorDodge

这里写图片描述

alignment

控制图片的摆放位置。如下将图片放置在右下角。其他的位置自行尝试。

alignment: Alignment.bottomRight,

这里写图片描述

repeat

一图胜前言

    Image image = new Image.asset(
      'imgs/logo.jpeg',
      width: 400.0,
      height: 500.0,
      fit: BoxFit.scaleDown,
      repeat: ImageRepeat.repeat,
    );
repeat Results
ImageRepeat.repeat 这里写图片描述
ImageRepeat.repeatX 这里写图片描述
ImageRepeat.repeatY 这里写图片描述
ImageRepeat.none 这里写图片描述

centerSlice

当图片需要被拉伸显示的时候,centerSlice定义的矩形区域会被拉伸,可以理解成我们在图片内部定义来一个点9文件用作拉伸。

    Image image = new Image.asset(
      'imgs/logo.jpeg',
      width: 500.0,
      height: 500.0,
      fit: BoxFit.contain,
      centerSlice: new Rect.fromCircle(center: const Offset(100.0, 100.0), radius: 10.0 ),
    );

这里写图片描述
注意一下这部分,代码中有如是一段:

assert(sourceSize == inputSize, 'centerSlice was used with a BoxFit that does not guarantee that the image is fully visible.');

也就是说只有在显示大小大于原图大小的情况下,才允许使用这个属性,否则会报错。

matchTextDirection

与Directionality配合使用

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    Image image = new Image.asset(
      'imgs/android.jpg',
      fit: BoxFit.scaleDown,
      matchTextDirection: true,
    );
    return new Scaffold(
        appBar: new AppBar(title: new Text("Image Test"),
          centerTitle: true,),
        body: new ListView(

          children: <Widget>[
            new Directionality(
              textDirection: TextDirection.ltr,
              child: image,
            ),
            new Directionality(
              textDirection: TextDirection.rtl,
              child: image,
            ),
          ],
        )
    );
  }

列表中两个图片,第一个是TextDirection.ltr,第二个TextDirection.rtl。
这里写图片描述

gaplessPlayback

当ImageProvider发生变化后,重新加载图片的过程中,原图片的展示是否保留。若值为true,保留,若为false,不保留,直接空白等待下一张图片加载。

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;
  NetworkImage networkImage = new NetworkImage("https://flutter.io/images/homepage/header-illustration.png");

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
        appBar: new AppBar(title: new Text("Image Test"),
          centerTitle: true,),
        body: new ListView(
          children: <Widget>[
            new Directionality(
              textDirection: TextDirection.ltr,
              child: new Image(image: widget.networkImage, fit: BoxFit.contain,gaplessPlayback: true,),
            ),
            new InkWell(
              child: new Text("点击我切换图片", textAlign: TextAlign.center,),
              onTap: (){
                setState(() {
                  print("change pic");
                  widget.networkImage = new NetworkImage("https://flutter.io/images/intellij/hot-reload.gif");
                });
              },)
          ],
        )
    );
  }
}
gaplessPlayback Result
true 这里写图片描述
false 这里写图片描述