正所谓一图胜千言,一张意思清晰明了的图片胜过 N 句废话,所以图片的展示是相当重要的,Image 是 Flutter 用于展示图片的控件,它可以加载项目内的图片、手机存储中的图片以及直接从网络加载图片,不用再集成图片加载框架就可以加载网络图片这就很方便了。
1 构造方法
Image({Key key, @required ImageProvider image, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low })
创建一个 Image 组件,其中一个必传参数为 ImageProvider,它指定了图片是从哪里加载,是从项目中还是网络中等等。
Image.asset(String name, { Key key, AssetBundle bundle, String semanticLabel, bool excludeFromSemantics: false, double scale, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, String package, FilterQuality filterQuality: FilterQuality.low })
创建一个从项目中的资源目录加载图片的 Image,其实就相当于第一种构造方法指定 ImageProvider 为 AssetImage。
Image.file(File file, { Key key, double scale: 1.0, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low })
创建一个从手机存储目录加载图片的 Image,其实就相当于第一种构造方法指定 ImageProvider 为 FlieImage。
Image.memory(Uint8List bytes, { Key key, double scale: 1.0, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low })
应该是创建一个从内存或者字节流加载图片的 Image,其实就相当于第一种构造方法指定 ImageProvider 为 MemoryImage。
Image.network(String src, { Key key, double scale: 1.0, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low, Map<String, String> headers })
创建一个从网络加载图片的 Image,其实就相当于第一种构造方法指定 ImageProvider 为 NetworkImage。
其实后四种构造方法就相当于对第一种构造方法进行了封装,不用传入 ImageProvider 而已,但是仍要传入图片路径,所以说也没省多大事,我比较倾向用第一种构造方法。
2 常用属性
image:从哪里加载图片,值为一个 ImageProvider 对象,ImageProvider 的实现类有 AssetBundleImageProvider(AssetImage 继承自它)、FileImage、MemoryImage、NetworkImage,需要注意的是,如果选择 AssetImage 从资源目录中加载图片,需在 pubspec.yaml 配置文件中配置 assets 目录:
必须是上面的层级关系,但是感觉从资源目录加载图片老有问题,有时候显示不出来但又不报错,可以试试目录后面跟上具体文件名,即:
但是这样每张图片都得配置,未免太过麻烦,而选择 NetworkImage 从网络加载图片就简单多了,只需要指定图片的 url 即可。
width 和 heigh:宽和高,不必赘述。
alignment:如果图片没有填充满容器的话,图片的对齐方式,值为一个 AlignmentGeometry 对象,Alignment 是它的一个实现类,可选值同 Container 的 Alignment 取值一样。
Alignment.topLeft:垂直靠顶部水平靠左对齐。
Alignment.topCenter:垂直靠顶部水平居中对齐。
Alignment.topRight:垂直靠顶部水平靠右对齐。
Alignment.centerLeft:垂直居中水平靠左对齐。
Alignment.center:垂直和水平居中都对齐。
Alignment.centerRight:垂直居中水平靠右对齐。
Alignment.bottomLeft:垂直靠底部水平靠左对齐。
Alignment.bottomCenter:垂直靠底部水平居中对齐。
Alignment.bottomRight:垂直靠底部水平靠右对齐。
除了上面的常量之外,还可以创建 Alignment 对象指定 x、y 偏移量。
color:在图片上设置颜色,值为一个 Color 对象,会覆盖 image 指定的图片,如果也设置了 colorBlendMode 属性,则会与 image 混合产生特殊效果。
colorBlendMode:颜色混合模式,类似 BoxDecoration 的 backgroundBlendMode。
excludeFromSemantics:是否启用图像的语义描述。
filterQuality:图像过滤器的质量级别(使用该属性还没看到效果,后面用到了再研究)。
fit:图片的缩放方式,类似 Android 中 ImageView 的 scaleType,可选值有:
BoxFit.none:将图片的内容按原大小居中显示。
BoxFit.contain:将图片的内容完整居中显示,通过按比例缩小或原来的 size 使得图片宽/高等于或小于组件的宽/高,类似 Android 的 centerInside。
BoxFit.cover:按比例放大图片的 size 居中显示,类似 Android 的 centerCrop。
BoxFit.fill:把图片不按比例放大/缩小到组件的大小显示,类似 Android 的 fitXY。
BoxFit.fitHeight:把图片的高按照组件的高显示,宽等比例放大/缩小。
BoxFit.fitWidth:把图片的宽按照组件的宽显示,高等比例放大/缩小。
BoxFit.scaleDown:如果图片宽高大于组件宽高,则让图片内容完全居中显示,此时同 contain,如果图片宽高小于组件宽高,则按图片原大小居中显示,此时同 none。
centerSlice:该属性用于 .9 图的中心拉伸,值为一个 Rect 对象,应该就是拉伸区域,我在使用该属性的时候只有当 fit 设置为 contain 和 fill 时才看到了效果,该属性应该也是用于图形变换,不常用。
gaplessPlayback:当 ImageProvider 发生变化后,重新加载图片的过程中,原图片的展示是否保留。true 表示保留,false 表示不保留,直接空白等待下一张图片加载。
matchTextDirection:该属性值表示图片的方向是否跟随文字的方向,其实就相当于左右翻转,true 表示翻转,false 表示不翻转,但是要想该属性生效,必须使用 Directionality 组件包裹 Image 组件,如下面代码:
new Directionality(
textDirection: TextDirection.rtl,
child: new Image(
image: new NetworkImage(imgUrl),
matchTextDirection: true,
),
)
上面代码中的 textDirection 属性值为 TextDirection.rtl,即从右向左,然后 Image 组件的图片方向跟随文字方向也是从右向左,即相当于左右翻转的效果。
repeat:如果图片没填充满容器的话,图片的重复方式,可选值有:
ImageRepeat.noRepeat:不重复。
ImageRepeat.repeat:X、Y 轴都重复。
ImageRepeat.repeatX:只在 X 轴重复。
ImageRepeat.repeatY:只在 Y 轴重复。
semanticLabel:图像的语义描述,类似 Android 中 ImageView 的 contentDescription 属性。
下面是一个设置了上面部分属性的 Image 组件的 demo:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// var imgUrl =
// "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1545191828292&di=caef0d773e90142191de9fc5f5871cef&imgtype=0&src=http%3A%2F%2Fimg.mp.sohu.com%2Fq_mini%2Cc_zoom%2Cw_640%2Fupload%2F20170807%2Fb008bbf3df1b490d85e3ff3152ea898e_th.jpg";
var imgUrl =
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1545790666&di=45beff1e706ea81d796d2268553c9e6f&imgtype=jpg&er=1&src=http%3A%2F%2Fp1.music.126.net%2FfydScGuKzV4GFdqeCMKhxQ%3D%3D%2F109951163178133629.jpg%3Fparam%3D180y180";
return MaterialApp(
//是否显示 debug 标签
debugShowCheckedModeBanner: false,
title: "Image",
home: Scaffold(
appBar: new AppBar(
title: new Text("Image"),
),
body: new Container(
color: new Color(0xFFFF0000),
//子组件
child: new Image(
//从资源目录中加载图片,需在 pubspec.yaml 配置文件中配置 assets 目录
//flutter:
// assets:
// - assets/images/
//必须是上面的层级关系,但是感觉从资源目录加载图片老有问题,有时候显示不出来但又不报错,可以试试目录后面跟上具体文件名,即
//flutter:
// assets:
// - assets/images/iverson.jpg
//但是这样每张图片都得配置,未免太过麻烦
// image: new AssetImage("assets/images/iverson.jpg"),
//从网络加载图片,非常容易,不用配置,而且只要有网就没什么问题
image: new NetworkImage(imgUrl),
width: 300,
height: 200,
//如果图片没有填充满容器的话,图片的对齐方式,值为一个 AlignmentGeometry 对象,Alignment 是它的一个实现类
//可选值同 Container 的 Alignment 取值一样。
//Alignment.topLeft:垂直靠顶部水平靠左对齐
//Alignment.topCenter:垂直靠顶部水平居中对齐
//Alignment.topRight:垂直靠顶部水平靠右对齐
//Alignment.centerLeft:垂直居中水平靠左对齐
//Alignment.center:垂直和水平居中都对齐
//Alignment.centerRight:垂直居中水平靠右对齐
//Alignment.bottomLeft:垂直靠底部水平靠左对齐
//Alignment.bottomCenter:垂直靠底部水平居中对齐
//Alignment.bottomRight:垂直靠底部水平靠右对齐
//除了上面的常量之外,还可以创建 Alignment 对象指定 x、y 偏移量
alignment: Alignment.center,
//在图片上设置颜色,值为一个 Color 对象,会覆盖 image 指定的图片,如果也设置了 colorBlendMode 属性,则会与 image 混合产生特殊效果
color: new Color(0xFFFFFF00),
//颜色混合模式,类似 BoxDecoration 的 backgroundBlendMode
colorBlendMode: BlendMode.darken,
// excludeFromSemantics: true,
// filterQuality: FilterQuality.high,
//图片的缩放方式,类似 Android 中 ImageView 的 scaleType,可选值有:
//BoxFit.none:将图片的内容按原大小居中显示。
//BoxFit.contain:将图片的内容完整居中显示,通过按比例缩小或原来的 size 使得图片宽/高等于或小于组件的宽/高,类似 Android 的 centerInside。
//BoxFit.cover:按比例放大图片的 size 居中显示,类似 Android 的 centerCrop。
//BoxFit.fill:把图片不按比例放大/缩小到组件的大小显示,类似 Android 的 fitXY。
//BoxFit.fitHeight:把图片的高按照组件的高显示,宽等比例放大/缩小。
//BoxFit.fitWidth:把图片的宽按照组件的宽显示,高等比例放大/缩小。
//BoxFit.scaleDown:如果图片宽高大于组件宽高,则让图片内容完全居中显示,此时同 contain,如果图片宽高小于组件宽高,则按图片原大小居中显示,此时同 none。
fit: BoxFit.contain,
// centerSlice:new Rect.fromCircle(center: Offset(100.0, 100.0), radius: 10.0),
// gaplessPlayback: true,
matchTextDirection: true,
//如果图片没填充满容器的话,图片的重复方式,可选值有:
//ImageRepeat.noRepeat:不重复
//ImageRepeat.repeat:X、Y 轴都重复
//ImageRepeat.repeatX:只在 X 轴重复
//ImageRepeat.repeatY:只在 Y 轴重复
repeat: ImageRepeat.noRepeat,
// semanticLabel: "",
),
),
),
);
}
}
运行效果如下:
3 总结
Flutter 加载网络图片比起 Android 要略微简单一些,不过要是加载项目包中的图片可能还需要一些配置,这个可以是利弊皆有,最常用的 Text 和 Image 组件看过后发现其实并不难,还有什么理由不继续,加油少年。