前言
在flutter中显示图片的就是Image,相当于android中的ImageView,但是要比ImageView功能强大很多。
比如支持gif动图,可以加载网络图片,缓存机制,图片处理等。实际上Image基本上实现了平时我们用到的图片加载框架(如glide)的大部分功能。
Image
根据加载图片的不同,可以使用不同的Image函数
- Image.asset 加载项目内资源
- Image.file 加载内存卡图片
- Image.memory 加载byte[]数据
- Image.network 加载网络图片
使用起来也很简单,如:
Image.file(File("xxx/xxxx/xxx.jpg")) 复制代码
当然这只是最简单的使用,函数中还有很多属性可以设置,以达到不同的效果
比如图片填充方式
Image.file(File("xxx/xxxx/xxx.jpg"), fit: BoxFit.cover) 复制代码
设置fit这个属性就可以了,cover表示图片宽高比不变,切割图片。
其他属性就不一一介绍了。
resize和缓存
当加载超大图片的时候,我们为了节省内存空间,需要将图片压缩成小尺寸再进行加载,即resize。
在Image中,resize是通过cacheWidth和cacheHeight这两个属性来处理的,同时也进行了缓存。
如:
Image.file( File("xxx/xxxx/xxx.jpg"), fit: BoxFit.cover, filterQuality: FilterQuality.low, cacheWidth: window.physicalSize.width ~/ 3, ) 复制代码
这里将cacheWidth设为屏幕宽度的1/3。
加载图片的时候会先处理图片,将读到内存中的图片数据的压缩到宽度等于屏幕宽度的1/3,然后将新的小的图片数据缓存起来,再加载显示。
后面我们如果还用到了这个图片,且cacheWidth设置一样,就可以直接从缓存中取出数据加载显示。
当然如果cacheWidth设置不一样,就要重新再处理一次图片。
cacheWidth和cacheHeight这两个属性可以同时设置,也可以只设置一个,如果不想改变图片的宽高比,就设置一个就可以了。
Hero闪烁问题
但是这里注意,当使用Hero将Image当作共享元素时,如果设置了cacheWidth会出现闪烁的情况(注:Hero是flutter中处理共享元素的组件)。
拖动消失问题
如果页面有拖动效果,这时发现当进行拖动时,设置了cacheWidth或cacheHeight的Image中的图片会消失,拖动结束后图片又出现。
解决方法,在image中添加gaplessPlayback: true
即可。
FadeInImage占位图
我们加载图片,尤其是网络图片的时候,需要先设置一个占位图。但是上面提到的几个函数都不存在相关的属性,怎么办呢?
我们可以使用FadeInImage,如下:
FadeInImage( placeholder: AssetImage("images/default.png"), image: FileImage(File("xxx/xxxx/xxx.jpg")), fadeOutDuration: Duration(milliseconds: 1), fadeInDuration: Duration(milliseconds: 1), ) 复制代码
这里placeholder就是占位图,而image就是真正加载的图片
注意这两个类型是ImageProvider,所以要使用FileImage、AssetImage等
FadeInImage在加载完成后替换占位图会执行一个渐出渐近的动画,所以也有相关的设置
比如fadeOutDuration和fadeInDuration设置动画的时长,fadeOutCurve和fadeInCurve可以设置动画曲线。
占位图解决,但是我们还想使用压缩和缓存怎么办?
可以使用ResizeImage解决,如下:
FadeInImage( placeholder: AssetImage("images/default.png"), image: ResizeImage(FileImage(File("xxx/xxxx/xxx.jpg")), width: window.physicalSize.width ~/ 3), fadeOutDuration: Duration(milliseconds: 1), fadeInDuration: Duration(milliseconds: 1), ) 复制代码
用ResizeImage将FileImage、AssetImage等包装一层就可以了。