老孟导读:大家好,这是【Flutter实战】系列文章的第三篇,这一篇讲解图片组件,Image有很多高级用法,希望对您有所帮助。

图片组件是Flutter基础组件之一,和文本组件一样必不可少。图片组件包含Image和Icon两个组件,本质上Icon不属于图片组件,但其外形效果上类似于图片。

在项目中建议优先使用Icon组件,Icon本质上是一种字体,只不过显示的不是文字,而是图标,而Image组件先通过图片解码器将图片解码,所以Icon有如下优点:

  • 通常情况下,图标比图片体积更小,显著的减少App包体积。
  • 图标不会出现失真或者模糊的现象,例如将20x20的图片,渲染在200x200的屏幕上,图片会失真或模糊,而图标是矢量图,不会失真,就像字体一样。
  • 多个图标可以存放在一个文件中,方便管理。
  • 全平台通用。

Image

Image组件用于显示图片,图片的来源可以是网络、项目中图片或者设备上的图片。

加载网络图片:

Image.network(
'http://pic1.win4000.com/pic/c/cf/cdc983699c.jpg',
)

加载项目中图片:

首先将图片拷贝到项目中,通常情况下,拷贝到assets/images/目录下,assets/images/目录为手动创建,新建的项目默认是没有此目录的。

设置pubspec.yaml配置文件:

assets:
- assets/images/

或者指定具体图片的名称:

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参数就是设置填充方式,其值介绍如下:

  • fill:完全填充,宽高比可能会变。
  • contain:等比拉伸,直到一边填充满。
  • cover:等比拉伸,直到2边都填充满,此时一边可能超出范围。
  • fitWidth:等比拉伸,宽填充满。
  • fitHeight:等比拉伸,高填充满。
  • none:当组件比图片小时,不拉伸,超出范围截取。
  • scaleDown:当组件比图片小时,图片等比缩小,效果和contain一样。

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,
),
),

colorcolorBlendMode用于将颜色和图片进行颜色混合,colorBlendMode表示混合模式,下面介绍的混合模式比较多,浏览一遍即可,此属性可以用于简单的滤镜效果。

  • clear:清楚源图像和目标图像。
  • color:获取源图像的色相和饱和度以及目标图像的光度。
  • colorBurn:将目标的倒数除以源,然后将结果倒数。
  • colorDodge:将目标除以源的倒数。
  • darken:通过从每个颜色通道中选择最小值来合成源图像和目标图像。
  • difference:从每个通道的较大值中减去较小的值。合成黑色没有效果。合成白色会使另一张图像的颜色反转。
  • dst:仅绘制目标图像。
  • dstATop:将目标图像合成到源图像上,但仅在与源图像重叠的位置合成。
  • dstIn:显示目标图像,但仅显示两个图像重叠的位置。不渲染源图像,仅将其视为蒙版。源的颜色通道将被忽略,只有不透明度才起作用。
  • dstOut:显示目标图像,但仅显示两个图像不重叠的位置。不渲染源图像,仅将其视为蒙版。源的颜色通道将被忽略,只有不透明度才起作用。
  • dstOver:将源图像合成到目标图像下。
  • exclusion:从两个图像的总和中减去两个图像的乘积的两倍。
  • hardLight:调整源图像和目标图像的成分以使其适合源图像之后,将它们相乘。
  • hue:获取源图像的色相,以及目标图像的饱和度和光度。
  • lighten:通过从每个颜色通道中选择最大值来合成源图像和目标图像。
  • luminosity:获取源图像的亮度,以及目标图像的色相和饱和度。
  • modulate:将源图像和目标图像的颜色分量相乘。
  • multiply:将源图像和目标图像的分量相乘,包括alpha通道。
  • overlay:调整源图像和目标图像的分量以使其适合目标后,将它们相乘。
  • plus:对源图像和目标图像的组成部分求和。
  • saturation:获取源图像的饱和度以及目标图像的色相和亮度。
  • screen:将源图像和目标图像的分量的逆值相乘,然后对结果求逆。
  • softLight:对于低于0.5的源值使用colorDodge,对于高于0.5的源值使用colorBurn。
  • src:放置目标图像,仅绘制源图像。
  • srcATop:将源图像合成到目标图像上,但仅在与目标图像重叠的位置合成。
  • srcIn:显示源图像,但仅显示两个图像重叠的位置。目标图像未渲染,仅被视为蒙版。目标的颜色通道将被忽略,只有不透明度才起作用。
  • srcOut:显示源图像,但仅显示两个图像不重叠的位置。
  • srcOver:将源图像合成到目标图像上。
  • xor:将按位异或运算符应用于源图像和目标图像。

是不是感觉看了和没看差不多,看了也看不懂。正常,估计只有学过视觉算法的才能看懂吧,直接看下各个属性的效果吧:

repeat表示当组件有空余位置时,将会重复显示图片

Image.asset(
'assets/images/aa.jpg',
width: double.infinity,
height: 150,
repeat: ImageRepeat.repeatX,
)

重复的模式有:

  • repeat:x,y方向都充满。
  • repeatX:x方向充满。
  • repeatY:y方向充满。
  • noRepeat:不重复。

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是图标组件,Icon不具有交互属性,如果想要交互,可以使用IconButton。

Icon(Icons.add),

设置图标的大小和颜色:

Icon(
Icons.add,
size: 40,
color: Colors.red,
)

上面的黑色为默认大小和颜色。

Icons.add是系统提供的图标,创建Flutter项目的时候,pubspec.yaml中默认有如下配置:

所有的图标在Icons中已经定义,可以直接在源代码中查看,也可以到官网查看所有图标

所有图标效果如下:

案例

聊天背景(.9图实现)

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】:

【Flutter实战】图片组件及四大案例的更多相关文章

  1. flutter的 图片组件基本使用

    import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends Statele ...

  2. 【Flutter 实战】简约而不简单的计算器

    老孟导读:这是 [Flutter 实战]组件系列文章的最后一篇,其他组件地址:http://laomengit.com/guide/widgets/Text.html,接下来将会讲解动画系列,关注老孟 ...

  3. 【Flutter实战】定位装饰权重组件及柱状图案例

    老孟导读:Flutter中有这么一类组件,用于定位.装饰.控制子组件,比如 Container (定位.装饰).Expanded (扩展).SizedBox (固定尺寸).AspectRatio (宽 ...

  4. Flutter实战】文本组件及五大案例

    老孟导读:大家好,这是[Flutter实战]系列文章的第二篇,这一篇讲解文本组件,文本组件包括文本展示组件(Text和RichText)和文本输入组件(TextField),基础用法和五个案例助你快速 ...

  5. 【Flutter实战】六大布局组件及半圆菜单案例

    老孟导读:Flutter中布局组件有水平 / 垂直布局组件( Row 和 Column ).叠加布局组件( Stack 和 IndexedStack ).流式布局组件( Wrap )和 自定义布局组件 ...

  6. Flutter学习笔记(10)--容器组件、图片组件

    如需转载,请注明出处:Flutter学习笔记(10)--容器组件.图片组件 上一篇Flutter学习笔记(9)--组件Widget我们说到了在Flutter中一个非常重要的理念"一切皆为组件 ...

  7. flutter图片组件

    在flutter中,image组件有很多构造函数,常用的包括Image.asset(本地图片)和Image.network(远程图片). 常用属性 不管是显示本地图片还是远程图片,image组件都包含 ...

  8. 【Flutter学习】基本组件之图片组件Image

    一,概述 Image(图片组件)是显示图像的组件,一个显示图片的widget,支持图像格式:JPEG,PNG,GIF,动画GIF,WebP,动画WebP,BMP和WBMP. Image组件有多种构造函 ...

  9. 【Flutter 实战】1.20版本更新及新增组件

    老孟导读:Flutter 1.20 更新了 Slider.RangeSlider.日期选择器组件.时间选择器组件的样式,新增了交换组件:InteractiveViewer,下面详细介绍其用法. 滑块 ...

随机推荐

  1. 服务治理:Spring Cloud Eureka

    Spring Cloud Eureka主要负责完成微服务架构中服务治理功能. 服务治理是微服务架构中最为核心和基础模块,主要用来实现各个微服务实例的自动注册和发现. 服务注册 微服务实例启动后向注册中 ...

  2. shrio的springboot完整配置

    package com.zys.sys.config; import java.util.HashMap; import java.util.Map; import javax.servlet.Fil ...

  3. 又抓了一个导致频繁GC的鬼--数组动态扩容

    概述 本周有个同事过来咨询一个比较诡异的gc问题,大概现象是,系统一直在做cms gc,但是老生代一直不降下去,但是执行一次jmap -histo:live之后,也就是主动触发一次full gc之后, ...

  4. 前端自动化构建之webpack

    前言 学了gulp后马上就开始学了一下webpack,所以马上来谈一下感受,感觉webpack有人说是一个模块化工具,用来和browserify来做比较,我感觉webpack牛逼多了,不但可以把复杂的 ...

  5. 【C++】C++数据类型

    注意:以下内容摘自文献[1],修改了部分内容. 计算机处理的对象是数据,而数据是以某种特定的形式存在的(例如整数.浮点数.字符等形式).数据结构指的是数据的组织形式.例如,数组就是一种数据结构. 1. ...

  6. Spring_使用外部属性文件&SpEL

    1.使用外部属性文件 beans-properties.xml <?xml version="1.0" encoding="UTF-8"?> < ...

  7. Rocket - debug - TLDebugModuleOuterAsync

    https://mp.weixin.qq.com/s/PSeMVZjSjEFHJgCYZzfa9Q 简单介绍TLDebugModuleOuterAsync的实现. 1. dmi2tl dmi2tl是T ...

  8. jchdl - GSL实例:FullAdder

    https://mp.weixin.qq.com/s/CtT08xZON0YxnheqDM2FAw 全加器是能够计算低位进位的二进制加法电路.与半加器相比,全加器不只考虑本位计算结果是否有进位,也考虑 ...

  9. Java实现 LeetCode 824 山羊拉丁文(暴力)

    824. 山羊拉丁文 给定一个由空格分割单词的句子 S.每个单词只包含大写或小写字母. 我们要将句子转换为 "Goat Latin"(一种类似于 猪拉丁文 - Pig Latin ...

  10. Java实现 蓝桥杯 算法训练 Beaver's Calculator

    试题 算法训练 Beaver's Calculator 问题描述 从万能词典来的聪明的海狸已经使我们惊讶了一次.他开发了一种新的计算器,他将此命名为"Beaver's Calculator ...