
Flutter 里面关于图片的内容挺多,大家好好看下:
IconImage关于图片的在 row、colomu 中的缩放image 开源组件阿里巴巴矢量图标字体SVG 矢量图支持
Icon
Flutter 非常贴心的提供了很多 MD 风格的 icon,于是这就有了Icon这个 Widget
Icon属性如下:
const Icon(this.icon, {
Key key,
this.size,
this.color,
this.semanticLabel, // 图片的描述,没啥用
this.textDirection,
})
class DD extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.access_alarm,
size: 50,
semanticLabel: "AAA",
),
],
);
}
}

- 其他的不用说,重点看
Icons这个类,这里面保存着所有 Flutter 内置的 icon 给我们使用,非常多
- 再一个就是
size了,Icon 天然的是正方形的, 大家注意 color是前景色,默认的是混合模式,color概念Icon图片的颜色,这里color给一个红色玩玩
class DD extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.access_alarm,
size: 50,
color: Colors.red,
semanticLabel: "AAA",
),
],
);
}
}

Image
一看名字大家就知道我们熟悉的回来了,属性值和 android 一样,下面就说说值得注意的点
const Image({
Key key,
@required this.image,
this.semanticLabel, // 图片的描述,没啥用
this.excludeFromSemantics = false, // 是否从语义上排除该图片,默认值为false
this.width,
this.height,
this.color, // 图片的前景色,和colorBlendMode结合使用
this.colorBlendMode,
this.fit, // 图片缩放模式
this.alignment = Alignment.center,
this.repeat = ImageRepeat.noRepeat,
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
this.filterQuality = FilterQuality.low,
})
1. 加载图片
Image widget 使用ImageProvider抽象类来提供图片资源,这是典型的接口模式,自然 Flutter 提供了多种ImageProvider抽象类实现,可以从:本地/网络/项目资源中读取图片,设计思路非常 nice,我是非常喜欢、欣赏的~

NetworkImage- 从网路加载图片
Image(
image: NetworkImage("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000"
"&sec=1567948974&di=cb4ccca1f7932dfdbf09eef5b1e6d4d3&imgtype=jpg&er=1&src="
"http%3A%2F%2Fwww.ahgame.com%2Fuploads%2Fallimg%2F161124%2F16112416235712.jpg"),
),
// 这样写也OK
Image.network(
"https://img-blog.csdnimg.cn/20181210151747299.jpg",
);

AssetImage- 加载 asset 资源图片
Image(
image: AssetImage("assets/icons/icon_2.jpg"),
),
// 或者这样
Image.asset("imgs/code.png");
2. Flutter 资源文件结构
Flutter 没有指定资源文件地址,全完是配置式的,随便你怎么组织文件形式,完事在pubspec.yaml文件中声明即可
图片可以每一张都在pubspec.yaml里面配置,但是这样图片多了的话很没麻烦的,不可能都写一遍吧。所以我们把图片放在一个固定的文件夹里,把文件夹地址配置到pubspec.yaml里面,注意该配置要写在pubspec.yaml文件的Flutter标签下:
ame: flutter_app4
description: A new Flutter application.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
# 图片资源配置
assets:
- assets/icons/
# 配置单张图片,一般不这么写,图片多了要写到什么时候去啊
- assets/icons/icon_1.gif
图片文件层级:

- 注意啊,对于
pubspec.yaml来说,最外层文件assets的子文件夹icons必须单独配置,是不能指望- assets/就把icons里面的图片逗声明进去的,必须给二级文件夹再声明一次- assets/icons/,这样配置是包含icons的子文件夹的内容的,不用再考虑三级文件夹的事,Google 这是设置是为了让我们把资源分门别类分好
代码:
class DD extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image(
image: AssetImage("assets/icons/icon_2.jpg"),
),
],
);
}
}

3. Fit 缩放
Image 只写宽或者高的时候,默认是按比例图片适配的,举个例子,我在外面包一层Container,蓝色背景
3.1 只是高度时: 是可以自动适配图片比例的
class DD extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
color: Colors.blue,
child: Image(
image: AssetImage("assets/icons/icon_3.png"),
height: 200,
),
),
],
);
}
}

3.2 宽高都写时: 就得注意对外层包裹容器大小的影响了
class DD extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
color: Colors.blue,
child: Image(
image: AssetImage("assets/icons/icon_3.png"),
width: 400,
height: 200,
),
),
],
);
}
}

3.3 fit 缩放模式
不详细展开了,大家看吧,应该都没问题的

4. BlendMode 颜色混合模式
Image里的color是前景色,写的话会覆盖图片,所以就需要和BlendMode颜色混合一起用了,Icon的color默认处理了,我们自己不能改,Image这里我们可以自由发挥了
Flutter 的BlendMode颜色混合模式是 android PorterDuffXferMode和前端background-blend-mode的混合,下面的模式都取自 android 和前端,这样吧我不详列出BlendMode的属性了,我把 android 的和前端的放出来,大家参考下
Flutter
android
前端
这些效果挺蛋疼的,我挨个试了一遍,效果明显的我截个图,省以后事了
原图如下,color 设置的红色:

下面是各种效果,大家自己看吧











关于图片的在 row、colomu 中的缩放
icon、image 在 row、colomu 中即便加上 expanded 壳,也不会占满父控件的全部,必须要借助 BoxConstraints 对子 widget 的强制约束才行,下面举个例子
例子1:
class EE extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
flex: 1,
child: Image.asset('assets/icons/icon_1.gif', fit: BoxFit.cover)),
Expanded(
flex: 1,
child: Image.asset('assets/icons/icon_2.jpg', fit: BoxFit.cover)),
Expanded(
flex: 1,
child: Image.asset('assets/icons/icon_3.png', fit: BoxFit.cover))
],
);
}
}

例子1 没达到我们想要占满全部宽度的想法......
例子2:
class FF extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
flex: 1,
child: ConstrainedBox(
child: Image.asset(
'assets/icons/icon_1.gif',
fit: BoxFit.cover,
),
constraints: new BoxConstraints.expand(),
)),
Expanded(
flex: 1,
child: ConstrainedBox(
child: Image.asset(
'assets/icons/icon_2.jpg',
fit: BoxFit.cover,
),
constraints: new BoxConstraints.expand(),
)),
Expanded(
flex: 1,
child: Container(
child: Image.asset('assets/icons/icon_3.png', fit: BoxFit.cover),
constraints: new BoxConstraints.expand(),
)),
],
);
}
}

BoxConstraints 盒子模型是会对子 widget 有强制约束的
image 开源组件
Flutter 原生的 image 组件功能很少,没有占位图,没有淡入淡出动画,只支持内存缓存,没有文件缓存,很硬伤的,所以有必要提到2个开源组件:
FadeInImage- 支持 loading 占位图CachedNetworkImage- 支持 loading、error 占位图,并且支持文件缓存
下面内容不难,我直接贴 Demo 了,其他属性大家也看的懂的~
FadeInImage
导包:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
transparent_image: ^1.0.0
// 有时候不用到这个包
import 'package:transparent_image/transparent_image.dart';
class EE extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FadeInImage.assetNetwork(
fadeInDuration: Duration(milliseconds: 300),
fadeOutDuration: Duration(milliseconds: 300),
fadeInCurve: Curves.easeInCirc,
placeholder: "assets/icons/icon_loading.gif",
image: "xxx",
);
}
}
fadeInCurve 属性是图片切换的动画, Curves 里预预置了很多
CachedNetworkImage
导包:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
cached_network_image: ^1.1.1
import 'package:cached_network_image/cached_network_image.dart';
class FF extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CachedNetworkImage(
placeholder: (context, url) => Image.asset("assets/icons/icon_loading.gif"),
errorWidget: (context, url, Object) => Image.asset("assets/icons/icon_loading.gif"),
imageUrl: "xxx",
);
}
}
阿里巴巴矢量图标字体
这个大家在 android 里应该都熟悉,阿里巴爸爸矢量图可以打包成ttf字体格式下载下来,当做字体来显示,原理和emoil表情一样
不过实测过后发现 Flutter 不支持阿里矢量库里的彩色 icon,会按照黑白来显示

阿里图片原样:

ttf 文件放置:

yaml
flutter:
uses-material-design: true
# 图片资源配置
assets:
- assets/icons/
fonts:
- family: font1
fonts:
- asset: assets/fonts/font_fangzheng_duhei.ttf
- family: font2
fonts:
- asset: assets/fonts/font_ali_f1.ttf
创建阿里图标对象:
import 'package:flutter/cupertino.dart';
class ALiFonts{
static const IconData realTime = IconData(0xe74b,fontFamily: "font2");
static const IconData computing = IconData(0xe743,fontFamily: "font2");
}
使用:
// Icon 承载阿里图标
class EE extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
ALiFonts.realTime,
size: 30,
),
Icon(
ALiFonts.computing,
size: 30,
),
],
);
}
}
注意:
- 阿里图标对应的
16进制标准样式:0xe74b,字幕自己写一遍,网站复制的话显示不出来,数值部分只取最后4位,0x是固定添加打头的
SVG 矢量图支持
我看有说法是:官方不打算支持 SVG,目前对于 SVG 有2种思路:
- 转换成
ttf使用 - 第三方库支持
1. SVG 转 ttf
官方提供:Flutter icon 库,可以提供 SVG 转 ttf 的服务

这种思路我不写了,大家看这篇介绍吧:Flutter 中使用svg资源
2. 开源组件:flutter_svg

flutter_svg 可以提供如原生 image 一样的使用体验
依赖:
dependencies:
flutter:
sdk: flutter
flutter_svg: ^0.14.1
图片路径:

使用:
import 'package:flutter_svg/flutter_svg.dart';
class EE extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
"assets/svgs/svg_1.svg",
width: 150,
height: 150,
color: Colors.red,
)
],
);
}
}
原理研究
这部分暂时没看,先方文章