前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Flutter 组件集录】FadeInImage| 8月更文挑战

【Flutter 组件集录】FadeInImage| 8月更文挑战

作者头像
张风捷特烈
发布2022-03-18 15:35:47
发布2022-03-18 15:35:47
1.5K00
代码可运行
举报
运行总次数:0
代码可运行
一、认识 FadeInImage 组件

我们都知道,图片无论是从资源、文件、网络加载,都不会立刻完成,这样会出现短暂的空白,尤其是网络图片。自己处理默认占位图也比较麻烦。FadeInImage 的作用就是:在目标图片加载完成前使用默认图片占位,加载完成后,目标图片会渐变淡入,默认图片会渐变淡出,这样可以既解决图片加载占位问题,渐变的动画在视觉上也不显突兀。本文,就来全面介绍一下 FadeInImage 组件的使用以及简单的源码实现。

1. FadeInImage 基本信息

首先,它是一个 StatelessWidget,就说明它本身不会维护复杂的状态类,只是在 build 方法中负责组件的构建。

在普通构造中,必须传入两个 ImageProvider 对象,image 表示待加载的目标图片资源,placeholder 表示目标图片加载过程中显示的占位图片资源。另外还有很多用于配置图片和动画的属性,后面再一一介绍。

代码语言:javascript
代码运行次数:0
运行
复制
final ImageProvider placeholder;
final ImageProvider image;
2.FadeInImage 的简单使用

只有知道两个图片资源就能最简单地使用 FadeInImage,另外可以通过 widthheight 限制图片的大小。下面头像是使用网络图片,黑色的是占位图,效果如下:

属性名

类型

默认值

用途

placeholder

ImageProvider

required

占位图片资源

image

ImageProvider

required

目标图片资源

width

double

null

图片宽

height

double

null

图片高

代码语言:javascript
代码运行次数:0
运行
复制
class FadeInImageDemo extends StatelessWidget{
  final headUrl =
      'https://sf1-ttcdn-tos.pstatp.com/img/user-avatar/5b2b7b85d1c818fa71d9e2e8ba944a44~300x300.image';
  @override
  Widget build(BuildContext context) {
    return FadeInImage(
      width: 100,
      height: 100,
      placeholder: AssetImage(
        'assets/images/default_icon.png',
      ),
      image: NetworkImage(headUrl),
    );
  }
}
3.FadeInImage 动画配置

淡出动画 fadeOut 是针对占位图 而言的,淡入动画 fadeIn 是针对目标图 而言的,我们可以配置两个动画的时长和曲线来达到期望的动画效果,如下是测试案例的效果:

属性名

类型

默认值

用途

fadeOutDuration

Duration

300 ms

占位图淡出时长

fadeOutCurve

Curves

Curves.easeOut

占位图淡出动画曲线

fadeInDuration

Duration

700 ms

目标图淡入时长

fadeInCurve

Curves

Curves.easeIn

目标图淡入动画曲线

代码语言:javascript
代码运行次数:0
运行
复制
FadeInImage(
  width: 100,
  height: 100,
  fadeOutDuration:Duration(seconds: 1),
  fadeOutCurve: Curves.easeOutQuad,
  fadeInDuration: Duration(seconds: 2),
  fadeInCurve: Curves.easeInQuad,
  placeholder: AssetImage(
    'assets/images/default_icon.png',
  ),
  image: NetworkImage(headUrl),
);
4.FadeInImage 的图片错误构建器

既然是图片加载,就可能出错,这两个 XXXErrorBuilder 就是用来处理当图片加载错误时应该如何显示。如果不处理,就会像下面这样:

我们可以指定 XXXErrorBuilder 回调来构建错误时显示的组件,如下当占位符错误,显示蓝色 Container 示意一下,你可以指定任意的 Widget

属性名

类型

默认值

用途

placeholderErrorBuilder

ImageErrorWidgetBuilder

null

占位图加载错误时构建器

imageErrorBuilder

ImageErrorWidgetBuilder

null

目标图加载错误时构建器

代码语言:javascript
代码运行次数:0
运行
复制
class FadeInImageDemo extends StatelessWidget{

  final headUrl =
      'https://sf1-ttcdn-tos.pstatp.com/img/user-avatar/5b2b7b85d1c818fa71d9e2e8ba944a44~300x300.image';

  @override
  Widget build(BuildContext context) {
    return
    FadeInImage(
      width: 100,
      height: 100,
      fadeOutDuration:Duration(seconds: 1),
      fadeOutCurve: Curves.easeOutQuad,
      fadeInDuration: Duration(seconds: 2),
      fadeInCurve: Curves.easeInQuad,
      placeholderErrorBuilder: _placeholderErrorBuilder,
      placeholder: AssetImage(
        'assets/images/default_icon2.png',
      ),
      image: NetworkImage(headUrl),
    );
  }

  Widget _placeholderErrorBuilder(BuildContext context, Object error, StackTrace? stackTrace) {
    return Container(
      width: 100,
      height: 100,
      color: Colors.blue,
    );
  }
}
5.FadeInImage 其他属性

剩下的几个属性都是传给 Image 的,也就是说作用和 Image 中的属性一致,这里就不展开了。

6.FadeInImage 的其他构造

除了普通构造之外,FadeInImage 还有 assetNetworkmemoryNetwork ,这两者只是占位组件是 asset 路径 还是 Uint8List 字节数组的区别。这两个构造的目的是便于使用,可以指定缩放以及宽高。

可以看到两个 ImageProvider 成员对象会通过 ResizeImage 进行处理,通过 ResizeImage 可以更改图片资源的大小,通常用于减少 ImageCache 的内存占用。

到这里,FadeInImage 的使用方面就介绍完了。下面来看一下,作为一个 StatelessWidget , FadeInImage 为什么可以执行这么复杂的组件内容变化。

二、 FadeInImage 组件的源码实现
1. FadeInImage 组件的构建

对于 StatelessWidget 而言,逻辑基本上只在 build 方法中如何构建组件。如下是 FadeInImage#build,会通过 _image 方法创建 result 组件,并且一个 frameBuilder 的构建回调,使用了 _AnimatedFadeOutFadeIn 组件。

如果 excludeFromSemantics=false 会套上一个语义组件,Semantics 。这就是 FadeInImage 构造的全部内容。

_image 方法就是根据入参和成员属性构建 Image 组件而已,也没什么特别的。现在核心就是 frameBuilder 的回调会构建 _AnimatedFadeOutFadeIn 。那 Image#frameBuilder 是什么时候会调用呢?先让子弹飞一会,现在看一下 _AnimatedFadeOutFadeIn 的实现。

2. _AnimatedFadeOutFadeIn 组件的实现

它继承自 ImplicitlyAnimatedWidget ,表示其是一个 隐式动画组件,在 AnimatedOpacity 一文中介绍过隐式组件的特性:外界只需要改变相关配置属性,进重构组件就能触发动画,无需操作动画控制器。

_AnimatedFadeOutFadeInState#build 中可以看出,淡入淡出的动画实现是通过两个 FadeTransition完成的,两者通过 Stack 叠合。这样看来是不是豁然开朗。

3. 渐变动画如何触发

AnimatedOpacity 一文中也说过,对于隐式组件,动画的启动是通过改变属性和重建组件,来触发 State#didUpdateWidget ,开启动画。

那问题来了,作为 StatelessWidgetFadeInImage ,如何重构 _AnimatedFadeOutFadeIn 。现在再来看 frameBuilder 就正是时候。Image 组件的 frameBuilder 是一个回调的构建,它会在 _ImageState 构建时触发。

第一次是图片没有加载:

第二次是图片加载完成:

属性变化 + 组件重构,从而触发隐式组件的动画启动,完成需求。可以看出 FadeInImage 是非常巧妙的。FadeInImage 的使用方式到这里就介绍完毕,那本文到这里就结束了,谢谢观看,明天见~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/08/10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、认识 FadeInImage 组件
  • 1. FadeInImage 基本信息
  • 2.FadeInImage 的简单使用
  • 3.FadeInImage 动画配置
  • 4.FadeInImage 的图片错误构建器
  • 5.FadeInImage 其他属性
  • 6.FadeInImage 的其他构造
  • 二、 FadeInImage 组件的源码实现
    • 1. FadeInImage 组件的构建
    • 2. _AnimatedFadeOutFadeIn 组件的实现
    • 3. 渐变动画如何触发
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档