Flutter开发 9.Widget-图片加载及展示详解(Image、Container、Decoration、Clip)

16 篇文章 0 订阅

Flutter开发 9.Widget-图片加载及展示详解(Image、Container、Decoration、Clip)

1. 静态资源配置

1.1 概念描述

Flutter应用程序可以包含代码和 assets(有时称为资源)。asset是打包到程序安装包中的,可在运行时访问。常见类型的asset包括静态数据(例如JSON文件),配置文件,图标和图片(JPEG,WebP,GIF,动画WebP / GIF,PNG,BMP和WBMP)。

1.2 资源配置方式

我们先添加一个图片资源文件到lib下的images目录中,我们用这张图片来做测试,下载到本地后,改名为avatar.png
头像
将图片COPY到lib/images目录下:
在这里插入图片描述
Flutter使用pubspec.yaml文件(位于项目根目录),来识别应用程序所需的asset。打开pubspec.yaml文件,添加图片文件的路径。

flutter:
 assets:
   - lib/images/avatar.png

到此资源文件设置就完成了。每当添加一个资源就需要在此配置一下。
如果找不到资源文件,先确认一下在每行前面加的空格数量是否正确,assets前面有2个空格,-前面有三个空格。

1.3 多分辨率适配

另外Flutter可以为当前设备加载适合其分辨率的图像。

 assets:
   - lib/images/avatar.png
   - lib/images/2.0x/avatar.png
   - lib/images/3.0x/avatar.png

2. Image组件

2.1 属性详细说明

属性名类型说明
imageImageProvider实现ImageProvider抽象类的所有对象
frameBuilderImageFrameBuilder通常用来显示图片加载成功前的默认图,或者从未加载到加载成功的一些动画效果。下面有示例
loadingBuilderImageLoadingBuilder图片加载进度的回调方法. 下面有示例
errorBuilderImageErrorWidgetBuilder图片加载出错失败时的回调方法
widthdouble图片的宽
heightdouble图片高度
colorColor图片的混合色值
colorBlendModeBlendMode混合模式
fitBoxFit缩放模式
alignmentAlignment对齐方式
repeatImageRepeat重复方式
semanticLabelString用于描述图片语义的字符串
excludeFromSemanticsbool是否启用图像的语义描述
isAntiAliasbool是否抗锯齿
filterQualityFilterQuality图片缩放时图片的质量 none low medium hight
centerSliceRect将图片设置成类似于安卓中的.9图,用于图片拉伸
gaplessPlaybackbool当 ImageProvider 发生变化后,重新加载图片时,新图显示前原图是否保留。

2.2 使用本地资源

void main() {
  runApp(MaterialApp(
      home: Scaffold(
          body: Center(
              child: Column(mainAxisSize: MainAxisSize.min, children: [
    spawnRegularText("本地图片:"),
    const Image(image: AssetImage("lib/images/avatar.png")),
  ])))));
}

直接用AssetImage 将本地的图片路径字符串传入就可以得到ImageProvider对像了。

class AssetImage extends AssetBundleImageProvider
abstract class AssetBundleImageProvider extends ImageProvider
直接运行就可以显示出图片了
在这里插入图片描述

2.3 repeat参数用法

void main() {
  runApp(MaterialApp(
      home: Scaffold(
          body: Center(
              child: Column(mainAxisSize: MainAxisSize.min, children: [
    spawnRegularText("本地图片:"),
    const SizedBox(
      width: 600,
      height: 200,
      child: Image(
        image: AssetImage("lib/images/avatar.png"),
        width: 120,
        height: 120,
        repeat: ImageRepeat.repeatX,
      ),
    ),
  
  ])))));
}

外层包了一个SizedBox为指定里边图片重复显示的最大宽度

枚举值说明
ImageRepeat.repeatX、Y 轴都重复
ImageRepeat.repeatX只在 X 轴重复
ImageRepeat.repeatY只在 Y 轴重复
ImageRepeat.noRepeat不重复

运行效果如下
在这里插入图片描述

2.4 colorBlendMode参数详解


void main() {
  runApp(MaterialApp(
      home: Scaffold(
          body: Center(
              child: Column(mainAxisSize: MainAxisSize.min, children: [
    spawnRegularText("本地图片:"),
    const Image(
      image: AssetImage("lib/images/avatar.png"),
      width: 120,
      height: 120,
      color: Colors.yellowAccent,
      colorBlendMode: BlendMode.colorBurn,
    ),
    const Image(
      image: AssetImage("lib/images/avatar.png"),
      width: 120,
      height: 120,
      color: Colors.purple,
      colorBlendMode: BlendMode.difference,
    ),
    const Image(
      image: AssetImage("lib/images/avatar.png"),
      width: 120,
      height: 120,
      color: Colors.red,
      colorBlendMode: BlendMode.xor,
    ),
  ])))));
}

因为这个枚举参数比较多,所以爪爪这边直接先运行先看一下效果:
在这里插入图片描述
为了便于直观的看到效果,爪爪将所有参数都运行一遍,截图列在右侧.

BlendMode枚举值说明预览图
clearDrop both the source and destination images, leaving nothing.(全清除,什么都不留)
srcDrop the destination image, only paint the source image.(删除目标图,只画原图,即:只显示你指定的color颜色)
dstDrop the source image, only paint the destination image.(只画目标图,不显示源图, 即:只显示图, color没用了)
srcOverComposite the source image over the destination image.(在目标图像上合成源图像。Colors.yellowAccent)在这里插入图片描述
dstOverComposite the source image under the destination image.(在目标图像下合成源图像。Colors.yellowAccent)在这里插入图片描述
srcInShow the source image, but only where the two images overlap. (显示源图像,但仅显示两个图像重叠的位置。)
srcOutShow the source image, but only where the two images do not overlap.(显示源图像,但仅在两个图像不重叠的地方显示。Colors.yellowAccent)在这里插入图片描述
dstOutShow the destination image, but only where the two images do not overlap.(显示目标图像,但仅在两个图像不重叠的地方显示。)
srcATopComposite the source image over the destination image, but only where it overlaps the destination.(在目标图像上合成源图像,但仅在其与目标重叠的位置合成。Colors.yellowAccent)在这里插入图片描述
dstATopComposite the destination image over the source image, but only where it overlaps the source.(在源图像上合成目标图像,但仅在其与源重叠的位置合成。)在这里插入图片描述
xorApply a bitwise xor operator to the source and destination images.(对源图像和目标图像应用按位异或运算。)在这里插入图片描述
plusSum the components of the source and destination images.(对源图像和目标图像的成份求和。Colors.red)在这里插入图片描述
modulateMultiply the color components of the source and destination images.(将源图像和目标图像的颜色分量相乘。Colors.red)在这里插入图片描述
screenFollowing blend modes are defined in the CSS Compositing standard.(CSS合成标准中定义了以下混合模式。Colors.red)在这里插入图片描述
overlayMultiply the components of the source and destination images after adjusting them to favor the destination.(将源图像和目标图像的分量相乘,然后调整它们以有利于目标。Colors.red)在这里插入图片描述
darkenComposite the source and destination image by choosing the lowest value from each color channel.(通过从每个颜色通道中选择最低值来合成源图像和目标图像。Colors.red)在这里插入图片描述
lightenComposite the source and destination image by choosing the highest value from each color channel.(通过从每个颜色通道中选择最高值来合成源图像和目标图像。Colors.red)在这里插入图片描述
colorDodgeDivide the destination by the inverse of the source.(将目标除以源的倒数。Colors.red)在这里插入图片描述
colorBurnDivide the inverse of the destination by the source, and inverse the result.(将目标的倒数除以源,然后将结果倒数。Colors.red)在这里插入图片描述
hardLightMultiply the components of the source and destination images after adjusting them to favor the source.(将源图像和目标图像的分量相乘,然后将它们调整为有利于源图像。Colors.red)在这里插入图片描述
softLightUse [colorDodge] for source values below 0.5 and [colorBurn] for source values above 0.5.(对于低于0.5的源值,使用[colorDodge],对于高于0.5的源值,使用[colorBurn]。 Colors.red)在这里插入图片描述
differenceSubtract the smaller value from the bigger value for each channel.(从每个通道的较大值中减去较小的值。 Colors.red)在这里插入图片描述
exclusionSubtract double the product of the two images from the sum of the two images.(从两个图像的总和中减去两个图像的乘积的两倍。Colors.red)在这里插入图片描述
multiplyMultiply the components of the source and destination images, including the alpha channel.(将源图像和目标图像的组件相乘,包括alpha通道。Colors.red)在这里插入图片描述
hueTake the hue of the source image, and the saturation and luminosity of the destination image.(获取源图像的色调,以及目标图像的饱和度和亮度。Colors.red)在这里插入图片描述
saturationTake the saturation of the source image, and the hue and luminosity of the destination image.(获取源图像的饱和度,以及目标图像的色调和亮度。Colors.red)在这里插入图片描述
colorTake the hue and saturation of the source image, and the luminosity of the destination image.(获取源图像的色调和饱和度,以及目标图像的亮度。Colors.red)在这里插入图片描述
luminosityTake the luminosity of the source image, and the hue and saturation of the destination image.(获取源图像的亮度,以及目标图像的色调和饱和度。Colors.red)在这里插入图片描述

2.5 NetworkImage

NetworkImage实现了ImageProvider投象类,他实现的是一个异步方式从网络下载图片的功能,我们将在演示代码中使用它来加载网络图片。他可以只传入一个图片的URL地址即可,使用特别方便。

  const factory NetworkImage(String url, { double scale, Map<String, String>? headers }) = network_image.NetworkImage;

2.6 frameBuilder详解

官方文档的原文说明如下:

If this is null, this widget will display an image that is painted as soon as the first image frame is available (and will appear to “pop” in if it becomes available asynchronously). Callers might use this builder to add effects to the image (such as fading the image in when it becomes available) or to display a placeholder widget while the image is loading.

大概意思就是:
如果该值为空,则该组件将在第一个图像帧可用时立即显示绘制的图像(如果异步可用,直接显示)。调用者可以使用此生成器向图像添加效果(例如,图像可用时淡入淡出),或者在加载图像时显示占位符组件。

按照官方的示例代码大概如下:

void main() {
  runApp(MaterialApp(
      home: Scaffold(
          body: Center(
              child: Column(mainAxisSize: MainAxisSize.min, children: [
    const SizedBox(height: 50, width: 1),
    spawnRegularText("网络图片:"),
    Image(image: const NetworkImage(
        "https://img-blog.csdnimg.cn/20190520151631821.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3h1YW53ZW5jaGFv,size_16,color_FFFFFF,t_70",
      ),
      frameBuilder: (BuildContext context, Widget child, int? frame,
          bool wasSynchronouslyLoaded) {
        if (wasSynchronouslyLoaded) return child;
        return AnimatedOpacity(
            opacity: frame == null ? 0 : 1,
            duration: const Duration(seconds: 4),
            curve: Curves.easeOut,
            child: child);
      },

运行效果如下:

frameBuilder渐变加载图片

2.7 loadingBuilder详解

loadingBuilder回调方法会在图片加载过程中不断的执行,可以实时的得到当前已经加载的进度。

loadingBuilder: (BuildContext context, Widget child,
          ImageChunkEvent? loadingProgress) {
        // ignore: avoid_print
        print("loadingBuilder: expectedTotalBytes=${loadingProgress?.expectedTotalBytes},cumulativeBytesLoaded=${loadingProgress?.cumulativeBytesLoaded}");

执行这段代码后,在一张图片加载中,可以看到打印的LOG:

flutter: loadingBuilder: expectedTotalBytes=null,cumulativeBytesLoaded=null
flutter: loadingBuilder: expectedTotalBytes=324457,cumulativeBytesLoaded=15831
flutter: loadingBuilder: expectedTotalBytes=324457,cumulativeBytesLoaded=73176
flutter: loadingBuilder: expectedTotalBytes=324457,cumulativeBytesLoaded=130519
flutter: loadingBuilder: expectedTotalBytes=324457,cumulativeBytesLoaded=179673
flutter: loadingBuilder: expectedTotalBytes=324457,cumulativeBytesLoaded=212439
flutter: loadingBuilder: expectedTotalBytes=324457,cumulativeBytesLoaded=253400
flutter: loadingBuilder: expectedTotalBytes=324457,cumulativeBytesLoaded=286168
flutter: loadingBuilder: expectedTotalBytes=324457,cumulativeBytesLoaded=324457
flutter: loadingBuilder: expectedTotalBytes=null,cumulativeBytesLoaded=null

我们可以为图片加载做一个加载中的状态,演示代码如下

void main() {
  runApp(MaterialApp(
      home: Scaffold(
          body: Center(
              child: Column(mainAxisSize: MainAxisSize.min, children: [
    const SizedBox(height: 50, width: 1),
    spawnRegularText("网络图片:"),
    Image(
      image: const NetworkImage(
        "https://img-blog.csdnimg.cn/20190520151631821.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3h1YW53ZW5jaGFv,size_16,color_FFFFFF,t_70",
      ),
      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,
          ),
        );
      },
    ),
  ])))));
}

运行效果如下:

loadingBuilder 加载动画效果

3.图片圆角实现

3.1 通过Container的decoration实现

3.1.1 Container简介

Container是一个组合类容器,它本身不对应具体的RenderObject,它是DecoratedBox、ConstrainedBox、Transform、Padding、Align等组件组合的一个多功能容器,所以我们只需通过一个Container组件可以实现同时需要装饰、变换、限制的场景。

属性名类型说明
colorColor背景色
decorationDecoration背景装饰器
foregroundDecorationDecoration前景装饰器
widthdouble容器的宽度
heightdouble容器的高度
constraintsBoxConstraints容器限制条件
childWidget包含在容器内的组件

3.1.2 BoxDecoration简介

可以在其子组件绘制前(或后)绘制一些装饰(Decoration),如背景、边框、渐变等。BoxDecoration定义如下:

属性名类型说明
colorColor颜色
imageDecorationImage装饰器图片资源
borderBoxBorder边框
borderRadiusBorderRadiusGeometry圆角
boxShadowList < BoxShadow >阴影
gradientGradient渐变色
backgroundBlendModeBlendMode背景混合模式
shapeBoxShape形状

3.1.3 演示实例

void main() {
  runApp(MaterialApp(
      home: Scaffold(
          body: Center(
              child: Column(mainAxisSize: MainAxisSize.min, children: [
    const SizedBox(height: 50, width: 1),
    spawnRegularText("网络图片:"),
    Container(
      width: 300,
      height: 300,
      decoration: const BoxDecoration(
        shape: BoxShape.circle,
        image: DecorationImage(
            image: NetworkImage(
              "https://img-blog.csdnimg.cn/20190520151631821.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3h1YW53ZW5jaGFv,size_16,color_FFFFFF,t_70",
            ),
            fit: BoxFit.fill),
      ),
    ),
  ])))));
}

运行一下这段代码,执行的效果如下:
在这里插入图片描述

3.2 通过Clip实现

3.2.1 Clip介绍

Flutter中提供了一些剪裁函数,用于对组件进行剪裁,返回的Clip也是一个组件的子类.

class ClipRRect extends SingleChildRenderObjectWidget
abstract class RenderObjectWidget extends Widget

Clip名称说明
ClipOval子组件为正方形时剪裁成内贴圆形;为矩形时,剪裁成内贴椭圆
ClipRRect将子组件剪裁为圆角矩形
ClipRect默认剪裁掉子组件布局空间之外的绘制内容(溢出部分剪裁)
ClipPath按照自定义的路径剪裁

3.2.2 ClipRect示例

void main() {
  runApp(MaterialApp(
      home: Scaffold(
          body: Center(
              child: Column(mainAxisSize: MainAxisSize.min, children: [
    const SizedBox(height: 50, width: 1),
    spawnRegularText("网络图片:"),
    ClipRRect(
      borderRadius: BorderRadius.circular(30),
      child: const Image(
          image: NetworkImage(
            "https://img-blog.csdnimg.cn/20190520151631821.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3h1YW53ZW5jaGFv,size_16,color_FFFFFF,t_70",
          ),
          width: 300,
          height: 300,
          fit: BoxFit.fill),
    ),
  ])))));
}

运行一下这段代码,执行的效果如下:
在这里插入图片描述

3.2.3 ClipOval示例

void main() {
  runApp(MaterialApp(
      home: Scaffold(
          body: Center(
              child: Column(mainAxisSize: MainAxisSize.min, children: [
    const SizedBox(height: 50, width: 1),
    spawnRegularText("网络图片:"),
    const ClipOval(
      child: Image(
          image: NetworkImage(
            "https://img-blog.csdnimg.cn/20190520151631821.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3h1YW53ZW5jaGFv,size_16,color_FFFFFF,t_70",
          ),
          width: 300,
          height: 300,
          fit: BoxFit.fill),
    ),
  ])))));
}

运行一下这段代码,执行的效果如下:
在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xuanwenchao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值