老孟导读:你们好,这是【Flutter实战】系列文章的第三篇,这一篇讲解图片组件,Image有不少高级用法,但愿对您有所帮助。html
图片组件是Flutter基础组件之一,和文本组件同样必不可少。图片组件包含Image和Icon两个组件,本质上Icon不属于图片组件,但其外形效果上相似于图片。git
在项目中建议优先使用Icon组件,Icon本质上是一种字体,只不过显示的不是文字,而是图标,而Image组件先经过图片解码器将图片解码,因此Icon有以下优势:github
Image组件用于显示图片,图片的来源能够是网络、项目中图片或者设备上的图片。算法
加载网络图片:api
Image.network( 'http://pic1.win4000.com/pic/c/cf/cdc983699c.jpg', )
加载项目中图片:微信
首先将图片拷贝到项目中,一般状况下,拷贝到assets/images/
目录下,assets/images/
目录为手动建立,新建的项目默认是没有此目录的。网络
设置pubspec.yaml
配置文件:app
assets: - assets/images/
或者指定具体图片的名称:ide
assets: - assets/images/aa.jpg
一般状况下,使用第一种方式,由于图片会有不少张,增长一张就这里配置一个太麻烦。性能
注意:assets前面的空格问题,极容易引起编译异常,正确格式以下:
加载图片:
Image.asset('assets/images/aa.jpg')
加载设备上的图片:
要加载设备(手机)上的图片首先须要获取设备图片的路径,因为不一样平台的路径不一样,所以路径的获取必须依靠原生支持,若是了解原生(Android和iOS)开发,能够直接使用MethodChannel获取路径,若是不懂原生(Android和iOS)开发,可使用第三方插件获取路径,这里推荐官方的path_provider。
加载设备上的图片:
Image.file(File('path'))
设置图片的大小:
Image.asset('assets/images/aa.jpg',width: 100,height: 200,),
当Image的大小和图片大小不匹配时,须要设置填充模式fit
,设置组件大小为150x150,
Container( color: Colors.red.withOpacity(.3), child: Image.asset('assets/images/aa.jpg',width: 150,height: 150), )
看到,图片左右两边有空白区域(浅红色填充的区域),若是想要图片充满整个区域,设置以下:
Container( color: Colors.red.withOpacity(.3), child: Image.asset('assets/images/aa.jpg',width: 150,height: 150,fit: BoxFit.fill,), )
虽然图片充满整个区域,但图片变形了,使图片等比拉伸,直到两边都充满区域:
Container( color: Colors.red.withOpacity(.3), child: Image.asset('assets/images/aa.jpg',width: 150,height: 150,fit: BoxFit.cover,), )
此时,图片未变形且两边都充满区域,不过图片被裁减了一部分。
fit
参数就是设置填充方式,其值介绍以下:
BoxFit.none
的裁减和alignment
相关,默认居中,
Image.asset( 'assets/images/aa.jpg', width: 150, height: 150, fit: BoxFit.none, alignment: Alignment.centerRight, ),
左边为原图。
设置对齐方式:
Container( color: Colors.red.withOpacity(.3), child: Image.asset( 'assets/images/aa.jpg', width: 150, height: 150, alignment: Alignment.centerLeft, ), ),
color
和colorBlendMode
用于将颜色和图片进行颜色混合,colorBlendMode
表示混合模式,下面介绍的混合模式比较多,浏览一遍便可,此属性能够用于简单的滤镜效果。
是否是感受看了和没看差很少,看了也看不懂。正常,估计只有学过视觉算法的才能看懂吧,直接看下各个属性的效果吧:
repeat
表示当组件有空余位置时,将会重复显示图片
Image.asset( 'assets/images/aa.jpg', width: double.infinity, height: 150, repeat: ImageRepeat.repeatX, )
重复的模式有:
matchTextDirection
设置为true时,图片的绘制方向为TextDirection设置的方向,其父组件必须为Directionality:
Directionality( textDirection: TextDirection.rtl, child: Image.asset( 'assets/images/logo.png', height: 150, matchTextDirection: true, )),
左边为原图,效果是左右镜像。
filterQuality
表示绘制图像的质量,从高到低为:high->medium->low->none。越高效果越好,越平滑,固然性能损耗越大,默认是low
,若是发现图片有锯齿,能够设置此参数。
当加载图片的时候回调frameBuilder
,当此参数为null时,此控件将会在图片加载完成后显示,未加载完成时显示空白,尤为在加载网络图片时会更明显。所以此参数能够用于处理图片加载时显示占位图片和加载图片的过渡效果,好比淡入淡出效果。
下面的案例是淡入淡出效果:
Image.network( 'https://flutter.github.io/assets-for-api-docs/assets/widgets/puffin.jpg', frameBuilder: (BuildContext context, Widget child, int frame, bool wasSynchronouslyLoaded) { if (wasSynchronouslyLoaded) { return child; } return AnimatedOpacity( child: child, opacity: frame == null ? 0 : 1, duration: const Duration(seconds: 2), curve: Curves.easeOut, ); }, )
loadingBuilder
参数比frameBuilder
控制的力度更细,能够获取图片加载的进度,下面的案例显示了加载进度条:
Image.network( 'https://flutter.github.io/assets-for-api-docs/assets/widgets/puffin.jpg', loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent loadingProgress) { if (loadingProgress == null) { return child; } return Center( child: CircularProgressIndicator( value: loadingProgress.expectedTotalBytes != null ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes : null, ), ); })
centerSlice
用于.9图,.9图用于拉伸图片的特定区域,centerSlice
设置的区域(Rect)就是拉伸的区域。.9图一般用于控件大小、宽高比不固定的场景,好比聊天背景图片等。
Container( width: 250, height: 300, decoration: BoxDecoration( image: DecorationImage( centerSlice: Rect.fromLTWH(20, 20, 10, 10), image: AssetImage( 'assets/images/abc.jpg', ), fit: BoxFit.fill))),
上面为原图,下面为拉伸的图片。
在使用时大几率会出现以下异常:
这是因为图片比组件的尺寸大,若是使用centerSlice
属性,图片必须比组件的尺寸小,通常状况下,.9图的尺寸都很是小。
Icon是图标组件,Icon不具备交互属性,若是想要交互,可使用IconButton。
Icon(Icons.add),
设置图标的大小和颜色:
Icon( Icons.add, size: 40, color: Colors.red, )
上面的黑色为默认大小和颜色。
Icons.add
是系统提供的图标,建立Flutter项目的时候,pubspec.yaml
中默认有以下配置:
全部的图标在Icons中已经定义,能够直接在源代码中查看,也能够到官网查看全部图标。
全部图标效果以下:
Container( width: 200, padding: EdgeInsets.only(left: 8,top: 8,right: 20,bottom: 8), decoration: BoxDecoration( image: DecorationImage( centerSlice: Rect.fromLTWH(20, 20, 1, 1), image: AssetImage( 'assets/images/chat.png', ), fit: BoxFit.fill)), child: Text('老孟,专一分享Flutter技术和应用实战。' '老孟,专一分享Flutter技术和应用实战。' '老孟,专一分享Flutter技术和应用实战。',), )
背景图片大小是57x80:
右侧三角已经不在中间了,若是想让其一直保持居中,修改拉伸区域:
centerSlice: Rect.fromLTWH(20, 10, 1, 60),
Container( width: 100, height: 100, padding: EdgeInsets.all(3), decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.blue), child: Container( decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( image: AssetImage('assets/images/aa.jpg'), fit: BoxFit.cover)), ), )
Image.network( 'https://flutter.github.io/assets-for-api-docs/assets/widgets/puffin.jpg', height: 150, width: 150, fit: BoxFit.cover, frameBuilder: ( BuildContext context, Widget child, int frame, bool wasSynchronouslyLoaded, ) { if (frame == null) { return Image.asset( 'assets/images/place.png', height: 150, width: 150, fit: BoxFit.cover, ); } return child; }, )
若是系统提供的图标没有咱们想要的图标,这时须要引入第三方库的图标,下面以阿里巴巴的图标库为例。
打开阿里巴巴的图标官网,找到本身想要的图标后,将鼠标放置到图标上,加入购物车:
点击右上角的购物车,而后点击添加至项目:
若是没有添加过项目,须要建立一个新项目:
建立好后加入此项目,跳转到个人项目
页面,点击下载:
解压下载的文件,解压出来的文件有好几个,以下图:
选择iconfont.ttf
文件拷贝到 Flutter 项目的assets/fonts
目录下,assets/fonts
目录默认是没有的,须要手动建立,在pubspec.yaml
设置以下:
千万注意红框内开头的空格问题,不然编译不经过,family
后面跟的字符串最好有意义,后面用图标的时候须要用到。
用法以下:
Icon(IconData(0xe613,fontFamily: 'appIconFonts')
0xe613
在下载图标时已经标注,将&#
替换为0
,以下图:
fontFamily
是在pubspec.yaml
中设置的family
属性,第三方的图标和系统图标同样,能够设置其颜色和大小。
老孟Flutter博客地址(330个控件用法):http://laomengit.com
欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:
![]() |
![]() |