前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter组件学习(二)—— Image

Flutter组件学习(二)—— Image

作者头像
用户2802329
发布2018-12-21 11:53:01
1.4K0
发布2018-12-21 11:53:01
举报
文章被收录于专栏:Android先生Android先生

序言

上一节中,我们讲了 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,基本上所有形式的图片加载都是依赖它,这个类里面就是实现图片加载的原理。用法如下:

代码语言:javascript
复制
1new Image(image: new AssetImage('images/logo.png'));
2
3new 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 文件中声明一下:

代码语言:javascript
复制
 1flutter:
 2
 3  # The following line ensures that the Material Icons font is
 4  # included with your application, so that you can use the icons in
 5  # the material Icons class.
 6  uses-material-design: true
 7  assets:
 8    - images/logo.png
 9    - images/2.0x/logo.png
10    - images/3.0x/logo.png

用法如下:

代码语言:javascript
复制
1new Image.asset('images/logo.png')
3、Image.file

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

代码语言:javascript
复制
1new Image.file(new File('/storage/xxx/xxx/test.jpg'))
4、Image.network

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

代码语言:javascript
复制
1new Image.network('http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg')

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

代码语言:javascript
复制
 1new FadeInImage.assetNetwork(
 2  placeholder: 'images/logo.png',
 3  image: imageUrl,
 4  width: 120,
 5  fit: BoxFit.fitWidth,
 6)
 7
 8new FadeInImage.memoryNetwork(
 9  placeholder: kTransparentImage,
10  image: imageUrl,
11  width: 120,
12  fit: BoxFit.fitWidth,
13)

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

代码语言:javascript
复制
1new CachedNetworkImage(
2  width: 120,
3  fit: BoxFit.fitWidth,
4  placeholder: new CircularProgressIndicator(),
5  imageUrl: imageUrl,
6  errorWidget: new Icon(Icons.error),
7)

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

5、Image.memory

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

代码语言:javascript
复制
1new 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属性介绍:https://docs.flutter.io/flutter/dart-ui/BlendMode-class.html看看

实现圆角/圆形图片

1、圆角

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

代码语言:javascript
复制
 1使用裁剪来实现图片圆角:
 2
 3new ClipRRect(
 4  child: Image.network(
 5    imageUrl,
 6    scale: 8.5,
 7    fit: BoxFit.cover,
 8  ),
 9  borderRadius: BorderRadius.only(
10    topLeft: Radius.circular(20),
11    topRight: Radius.circular(20),
12  ),
13)
14
15使用边框来实现图片圆角:
16
17new Container(
18  width: 120,
19  height: 60,
20  decoration: BoxDecoration(
21    shape: BoxShape.rectangle,
22    borderRadius: BorderRadius.circular(10.0),
23    image: DecorationImage(
24        image: NetworkImage(imageUrl),
25        fit: BoxFit.cover),
26  ),
27)

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

2、圆形

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

代码语言:javascript
复制
 1使用裁剪实现圆形图片:
 2
 3new ClipOval(
 4    child: Image.network(
 5    imageUrl,
 6    scale: 8.5,
 7  ),
 8)
 9
10使用CircleAvatar来实现圆形图片:
11
12new CircleAvatar(
13  backgroundImage: NetworkImage(imageUrl),
14  radius: 50.0,
15)

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

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

代码语言:javascript
复制
  1class _ImageViewWidget extends State<ImageViewWidget> {
  2  var imageUrl =
  3      "http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg";
  4
  5  var imageUrl2 =
  6      "http://n.sinaimg.cn/sports/2_img/upload/4f160954/107/w1024h683/20181128/Yrxn-hpinrya6814381.jpg";
  7
  8  @override
  9  Widget build(BuildContext context) {
 10    return new Align(
 11      child: ListView(
 12        children: <Widget>[
 13          new Text('资源图片:'),
 14          new Row(
 15            mainAxisAlignment: MainAxisAlignment.center,
 16            children: <Widget>[
 17              new Padding(
 18                padding: const EdgeInsets.all(10.0),
 19                child: Image.asset(
 20                  'images/logo.png',
 21                ),
 22              ),
 23//              new Image.file(
 24//                File('/storage/emulated/0/Download/test.jpg'),
 25//                width: 120,
 26//                //fill(全图显示且填充满,图片可能会拉伸),contain(全图显示但不充满,显示原比例),cover(显示可能拉伸,也可能裁剪,充满)
 27//                //fitWidth(显示可能拉伸,可能裁剪,宽度充满),fitHeight显示可能拉伸,可能裁剪,高度充满),scaleDown(效果和contain差不多,但是)
 28//              ),
 29            ],
 30          ),
 31          new Text('网络占位图片CachedNetworkImage:'),
 32          new Padding(
 33            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
 34            child: Row(
 35              mainAxisAlignment: MainAxisAlignment.center,
 36              children: <Widget>[
 37                Image.network(
 38                  imageUrl,
 39                  scale: 8.5,
 40                ),
 41                new Padding(
 42                  padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
 43                  child: CachedNetworkImage(
 44                    width: 120,
 45                    fit: BoxFit.fitWidth,
 46                    placeholder: Image(image: AssetImage('images/logo.png')),
 47                    imageUrl: imageUrl,
 48                    errorWidget: new Icon(Icons.error),
 49                  ),
 50                ),
 51                new CachedNetworkImage(
 52                  imageUrl: imageUrl,
 53                  width: 120,
 54                  fit: BoxFit.fitWidth,
 55                  placeholder: CircularProgressIndicator(),
 56                  errorWidget: new Icon(Icons.error),
 57                )
 58              ],
 59            ),
 60          ),
 61          new Text('网络占位图片FadeInImage:'),
 62          new Padding(
 63            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
 64            child: new Row(
 65              children: <Widget>[
 66                new FadeInImage.memoryNetwork(
 67                  placeholder: kTransparentImage,
 68                  image: imageUrl,
 69                  width: 120,
 70                  fit: BoxFit.fitWidth,
 71                ),
 72                new Padding(
 73                  padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
 74                  child: new FadeInImage.assetNetwork(
 75                    placeholder: 'images/logo.png',
 76                    image: imageUrl,
 77                    width: 120,
 78                    fit: BoxFit.fitWidth,
 79                  ),
 80                ),
 81              ],
 82              mainAxisAlignment: MainAxisAlignment.center,
 83            ),
 84          ),
 85          new Text('圆形圆角图片:'),
 86          new Padding(
 87            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
 88            child: Row(
 89              mainAxisAlignment: MainAxisAlignment.center,
 90              children: <Widget>[
 91                new ClipOval(
 92                  child: Image.network(
 93                    imageUrl,
 94                    width: 100,
 95                    height: 100,
 96                    fit: BoxFit.fitHeight,
 97                  ),
 98                ),
 99                new Padding(
100                  padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
101                  child: ClipOval(
102                    child: Image.asset(
103                      'images/logo.png',
104                      width: 100,
105                      height: 100,
106                      fit: BoxFit.fitHeight,
107                    ),
108                  ),
109                ),
110                new ClipRRect(
111                  child: Image.network(
112                    imageUrl,
113                    scale: 8.5,
114                    fit: BoxFit.cover,
115                  ),
116                  borderRadius: BorderRadius.only(
117                    topLeft: Radius.circular(20),
118                    topRight: Radius.circular(20),
119                  ),
120                )
121              ],
122            ),
123          ),
124          new Text('颜色混合图片:'),
125          new Padding(
126            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
127            child: Row(
128              mainAxisAlignment: MainAxisAlignment.center,
129              children: <Widget>[
130                new Image.asset(
131                  'images/logo.png',
132                  color: Colors.red,
133                  colorBlendMode: BlendMode.darken,
134                ),
135                new Padding(
136                  padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
137                  child: Image.network(
138                    imageUrl,
139                    scale: 8.5,
140                    colorBlendMode: BlendMode.colorDodge,
141                    color: Colors.blue,
142                  ),
143                ),
144              ],
145            ),
146          ),
147          new Text('centerSlice图片内部拉伸:'),
148          new Padding(
149            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
150            child: new Image.asset(
151              'images/logo.png',
152              width: 250,
153              height: 250,
154              fit: BoxFit.contain,
155              centerSlice:
156                  new Rect.fromCircle(center: const Offset(20, 20), radius: 1),
157            ),
158          ),
159          new Text('matchTextDirection图片内部方向'),
160          new Padding(
161            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
162            child: Row(
163              mainAxisAlignment: MainAxisAlignment.center,
164              children: <Widget>[
165                new Directionality(
166                  textDirection: TextDirection.ltr,
167                  child: Image.network(
168                    imageUrl,
169                    height: 100,
170                    matchTextDirection: true,
171                    fit: BoxFit.fitHeight,
172                  ),
173                ),
174                new Padding(
175                  padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
176                  child: Directionality(
177                    textDirection: TextDirection.rtl,
178                    child: Image.network(
179                      imageUrl,
180                      height: 100,
181                      matchTextDirection: true,
182                      fit: BoxFit.fitHeight,
183                    ),
184                  ),
185                ),
186              ],
187            ),
188          ),
189          new Text('点击替换图片'),
190          new Padding(
191            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
192            child: Row(
193              children: <Widget>[
194                new RaisedButton(
195                  onPressed: () {
196                    setState(() {
197                      widget.networkImage =
198                          new NetworkImage(imageUrl2, scale: 8.5);
199                    });
200                  },
201                  child: Text('点击更换图片'),
202                ),
203                new Image(
204                  gaplessPlayback: false,
205                  fit: BoxFit.contain,
206                  image: widget.networkImage,
207                ),
208              ],
209            ),
210          )
211        ],
212      ),
213    );
214  }
215}

代码已上传至Github:https://github.com/24Kshign/FlutterWorkSpace/tree/master/flutter_element

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-12-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT先森养成记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 序言
  • Image组件的构造方法
    • 1、Image
      • 2、Image.asset
        • 3、Image.file
          • 4、Image.network
            • 5、Image.memory
            • Text组件的API
            • 实现圆角/圆形图片
              • 1、圆角
                • 2、圆形
                相关产品与服务
                容器服务
                腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档