Flutter组件学习(二)—— Image

作者 : 开心源码 本文共7370个字,预计阅读时间需要19分钟 发布时间: 2022-05-12 共71人阅读

序言

上一节中,我们讲了 FlutterText 组件的少量用法以及 API,本节我们继续学习 Flutter 中的 Image 组件,同样先上图:

image

Image组件的构造方法

Android 中,我们都知道,图片的显示方式有很多,资源图片、网络图片、文件图片等等,在 Flutter 中也有多种方式,用来加载不同形式的图片:

  • Image:通过ImageProvider来加载图片
  • Image.asset:用来加载本地资源图片
  • Image.file:用来加载本地(File文件)图片
  • Image.network:用来加载网络图片
  • Image.memory:用来加载Uint8List资源(byte数组)图片
1、Image

Image 的一个参数是 ImageProvider,基本上所有形式的图片加载都是依赖它,这个类里面就是实现图片加载的原理。用法如下:

new Image(image: new AssetImage('images/logo.png'));new Image(image: new NetworkImage('http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg'))
2、Image.asset

加载一个本地资源图片,和 Android 一样,有多种分辨率的图片可供选择,但是沿袭的是 iOS 的图片风格,分为 1x2x3x,具体做法是在项目的根目录下创立两个文件夹,如下图所示:

image

而后需要在 pubspec.yaml 文件中公告一下:

flutter:  # The following line ensures that the Material Icons font is  # included with your application, so that you can use the icons in  # the material Icons class.  uses-material-design: true  assets:    - images/logo.png    - images/2.0x/logo.png    - images/3.0x/logo.png

用法如下:

new Image.asset('images/logo.png')
3、Image.file

加载一个本地 File 图片,比方相册中的图片,用法如下

new Image.file(new File('/storage/xxx/xxx/test.jpg'))
4、Image.network

加载一个网络图片,用法如下:

new Image.network('http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg')

有的时候我们需要像Android那样使用一个占位图或者者图片加载出错时显示某张特定的图片,这时候需要用到 FadeInImage 这个组件:

new FadeInImage.assetNetwork(  placeholder: 'images/logo.png',  image: imageUrl,  width: 120,  fit: BoxFit.fitWidth,)new FadeInImage.memoryNetwork(  placeholder: kTransparentImage,  image: imageUrl,  width: 120,  fit: BoxFit.fitWidth,)

第一种方法是加载一个本地的占位图,第二种是加载一个透明的占位图,但是需要注意的是,这个组件是不可以设置加载出错显示的图片的;这里有另一种方法可以使用第三方 packageCachedNetworkImage 组件:

new CachedNetworkImage(  width: 120,  fit: BoxFit.fitWidth,  placeholder: new CircularProgressIndicator(),  imageUrl: imageUrl,  errorWidget: new Icon(Icons.error),)

CachedNetworkImage 组件中的占位图是一个 Widget,这样的话即可以自己设置了,你想使用什么样的组件进行占位都行,同样加载出错的占位图也是一个组件,也可以自己定义;该组件也是通过缓存来加载图片的。

5、Image.memory

用来将一个 byte 数组加载成图片,用法如下:

new Image.memory(bytes)

Text组件的API

API名称功能
width & height用来指定显示图片区域的宽高(并非图片的宽高)
fit设置图片填充,相似于Android中的ScaleType
color & colorBlendMode这两个属性需要配合使用,就是颜色和图片混合,就相似于Android中的Xfermode
alignment用来控制图片摆放的位置
repeat用来设置图片重复显示(repeat-x水平重复,repeat-y垂直重复,repeat两个方向都重复,no-repeat默认情况不重复)
centerSlice设置图片内部拉伸,相当于在图片内部设置了一个.9图,但是需要注意的是,要在显示图片的大小大于原图的情况下才可以使用这个属性,要不然会报错
matchTextDirection这个需要配合Directionality进行使用
gaplessPlayback当图片发生改变之后,重新加载图片过程中的样式(1、原图片保留)

fit 属性中有很多值可以设置:

属性名称样式
BoxFit.contain全图居中显示但不充满,显示原比例
BoxFit.cover图片可能拉伸,也可能裁剪,但是充满容器
BoxFit.fill全图显示且填充满,图片可能会拉伸
BoxFit.fitHeight图片可能拉伸,可能裁剪,高度充满
BoxFit.fitWidth图片可能拉伸,可能裁剪,宽度充满
BoxFit.scaleDown效果和contain差不多, 但是只能缩小图片,不能放大图片

colorBlendMode 属性中有很多值可以设置,因为可选值太多,这里就不逐个详情了,有兴趣的可以去官网colorBlendMode属性详情看看

实现圆角/圆形图片

1、圆角

很多时候我们需要给图片设置圆角,那么在flutter中是怎样实现的呢?有很多种方法可以实现,下面我举两个例子:

使用裁剪来实现图片圆角:new ClipRRect(  child: Image.network(    imageUrl,    scale: 8.5,    fit: BoxFit.cover,  ),  borderRadius: BorderRadius.only(    topLeft: Radius.circular(20),    topRight: Radius.circular(20),  ),)使用边框来实现图片圆角:new Container(  width: 120,  height: 60,  decoration: BoxDecoration(    shape: BoxShape.rectangle,    borderRadius: BorderRadius.circular(10.0),    image: DecorationImage(        image: NetworkImage(imageUrl),        fit: BoxFit.cover),  ),)

需要注意的是,使用边框实现的时候要注意设置 fit 属性,不然效果也是有问题的,当然了你还可以使用 Material 组件来实现,这个大家可以自己去尝试。

2、圆形

圆形图片用得最多的应该是头像之类的,这种同样有多种方式可以实现,下面我也举两个例子:

使用裁剪实现圆形图片:new ClipOval(    child: Image.network(    imageUrl,    scale: 8.5,  ),)使用CircleAvatar来实现圆形图片:new CircleAvatar(  backgroundImage: NetworkImage(imageUrl),  radius: 50.0,)

当然了,你还可以使用边框 BoxDecoration 来实现,效果也是一样的。

下面来看一下详细的代码实现:

class _ImageViewWidget extends State<ImageViewWidget> {  var imageUrl =      "http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg";  var imageUrl2 =      "http://n.sinaimg.cn/sports/2_img/upload/4f160954/107/w1024h683/20181128/Yrxn-hpinrya6814381.jpg";  @override  Widget build(BuildContext context) {    return new Align(      child: ListView(        children: <Widget>[          new Text('资源图片:'),          new Row(            mainAxisAlignment: MainAxisAlignment.center,            children: <Widget>[              new Padding(                padding: const EdgeInsets.all(10.0),                child: Image.asset(                  'images/logo.png',                ),              ),//              new Image.file(//                File('/storage/emulated/0/Download/test.jpg'),//                width: 120,//                //fill(全图显示且填充满,图片可能会拉伸),contain(全图显示但不充满,显示原比例),cover(显示可能拉伸,也可能裁剪,充满)//                //fitWidth(显示可能拉伸,可能裁剪,宽度充满),fitHeight显示可能拉伸,可能裁剪,高度充满),scaleDown(效果和contain差不多,但是)//              ),            ],          ),          new Text('网络占位图片CachedNetworkImage:'),          new Padding(            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),            child: Row(              mainAxisAlignment: MainAxisAlignment.center,              children: <Widget>[                Image.network(                  imageUrl,                  scale: 8.5,                ),                new Padding(                  padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),                  child: CachedNetworkImage(                    width: 120,                    fit: BoxFit.fitWidth,                    placeholder: Image(image: AssetImage('images/logo.png')),                    imageUrl: imageUrl,                    errorWidget: new Icon(Icons.error),                  ),                ),                new CachedNetworkImage(                  imageUrl: imageUrl,                  width: 120,                  fit: BoxFit.fitWidth,                  placeholder: CircularProgressIndicator(),                  errorWidget: new Icon(Icons.error),                )              ],            ),          ),          new Text('网络占位图片FadeInImage:'),          new Padding(            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),            child: new Row(              children: <Widget>[                new FadeInImage.memoryNetwork(                  placeholder: kTransparentImage,                  image: imageUrl,                  width: 120,                  fit: BoxFit.fitWidth,                ),                new Padding(                  padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),                  child: new FadeInImage.assetNetwork(                    placeholder: 'images/logo.png',                    image: imageUrl,                    width: 120,                    fit: BoxFit.fitWidth,                  ),                ),              ],              mainAxisAlignment: MainAxisAlignment.center,            ),          ),          new Text('圆形圆角图片:'),          new Padding(            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),            child: Row(              mainAxisAlignment: MainAxisAlignment.center,              children: <Widget>[                new ClipOval(                  child: Image.network(                    imageUrl,                    width: 100,                    height: 100,                    fit: BoxFit.fitHeight,                  ),                ),                new Padding(                  padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),                  child: ClipOval(                    child: Image.asset(                      'images/logo.png',                      width: 100,                      height: 100,                      fit: BoxFit.fitHeight,                    ),                  ),                ),                new ClipRRect(                  child: Image.network(                    imageUrl,                    scale: 8.5,                    fit: BoxFit.cover,                  ),                  borderRadius: BorderRadius.only(                    topLeft: Radius.circular(20),                    topRight: Radius.circular(20),                  ),                )              ],            ),          ),          new Text('颜色混合图片:'),          new Padding(            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),            child: Row(              mainAxisAlignment: MainAxisAlignment.center,              children: <Widget>[                new Image.asset(                  'images/logo.png',                  color: Colors.red,                  colorBlendMode: BlendMode.darken,                ),                new Padding(                  padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),                  child: Image.network(                    imageUrl,                    scale: 8.5,                    colorBlendMode: BlendMode.colorDodge,                    color: Colors.blue,                  ),                ),              ],            ),          ),          new Text('centerSlice图片内部拉伸:'),          new Padding(            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),            child: new Image.asset(              'images/logo.png',              width: 250,              height: 250,              fit: BoxFit.contain,              centerSlice:                  new Rect.fromCircle(center: const Offset(20, 20), radius: 1),            ),          ),          new Text('matchTextDirection图片内部方向'),          new Padding(            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),            child: Row(              mainAxisAlignment: MainAxisAlignment.center,              children: <Widget>[                new Directionality(                  textDirection: TextDirection.ltr,                  child: Image.network(                    imageUrl,                    height: 100,                    matchTextDirection: true,                    fit: BoxFit.fitHeight,                  ),                ),                new Padding(                  padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),                  child: Directionality(                    textDirection: TextDirection.rtl,                    child: Image.network(                      imageUrl,                      height: 100,                      matchTextDirection: true,                      fit: BoxFit.fitHeight,                    ),                  ),                ),              ],            ),          ),          new Text('点击替换图片'),          new Padding(            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),            child: Row(              children: <Widget>[                new RaisedButton(                  onPressed: () {                    setState(() {                      widget.networkImage =                          new NetworkImage(imageUrl2, scale: 8.5);                    });                  },                  child: Text('点击更换图片'),                ),                new Image(                  gaplessPlayback: false,                  fit: BoxFit.contain,                  image: widget.networkImage,                ),              ],            ),          )        ],      ),    );  }}

代码已上传至Github

公众号

欢迎关注我的个人公众号【IT先森养成记】,专注大前台技术分享,包含Android,Java,Kotlin,Flutter,HTML,CSS,JS等技术;在这里你能得到的不止是技术上的提升,还有少量学习经验以及志同道合的朋友,赶快加入我们,一起学习,一起进化吧!!!

公众号:IT先森养成记

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Flutter组件学习(二)—— Image

发表回复