Flutter 组件 | FadeTransition 透明变化

一、认识 FadeTransition 组件

1. FadeTransition 基本信息

FadeTransition 作为一个 SingleChildRenderObjectWidget ,说明其可以传入一个子组件,且需要承担 创建和更新 RenderObject 的任务。其功能是由 RenderAnimatedOpacity 对象完成。

2. FadeTransition 的使用

FadeTransition 需要一个 Animation 类型的参数 opacity 。也就是说,在使用时我们需要提供动画对象。如下让内容渐变出现,时长 2 s 。

class FadeTransitionTest extends StatefulWidget {
  @override
  _FadeTransitionTestState createState() => _FadeTransitionTestState();
}

class _FadeTransitionTestState extends State<FadeTransitionTest>
    with SingleTickerProviderStateMixin 
{

  AnimationController _opacity;

  @override
  void initState() {
    super.initState();
    _opacity = AnimationController(vsync: this, duration: Duration(seconds: 2))
      ..forward();
  }

  @override
  void dispose() {
    _opacity.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return FadeTransition(
      opacity: _opacity,
      child:  buildContent(),
    );
  }

  Widget buildContent() {
    return Wrap(
      direction: Axis.vertical,
      alignment: WrapAlignment.center,
      spacing: 10,
      crossAxisAlignment: WrapCrossAlignment.center,
      children: [
        Image.asset(
          'assets/images/icon_head.webp',
          width: 80,
          height: 80,
        ),
        const Text('张风捷特烈',
                   style: TextStyle(fontSize: 16,fontWeight: FontWeight.bold),)
      ],
    );
  }
}

3.FadeTransition 的价值

Opacity 组件中,对 FadeTransition 的介绍是:它可以使用提供的 animation 进行高效的透明动画。与 FadeTransition 功能相似的是 AnimatedOpacity ,它内置动画器,使用者无须提供,用起来更方便。那为什么还要提供 FadeTransition 呢?

因为 FadeTransition 的动画对象由外界提供,操作起来更加灵活。 AnimatedOpacity 将其封装到内部,外界便无法访问。其实 AnimatedOpacity 组件本质就是对 FadeTransition 的一层封装,所以两者也没什么比较的必要, AnimatedOpacity 用起来更方便, FadeTransition 用起来更灵活,根据场景自行选择。

二、 FadeTransition 源码解读

1. FadeTransition 组件属性

最主要的属性是 Animation 型的 opacity ,当动画数值变化时,透明度会随之变化。

2. FadeTransition 维护的 RenderObject

作为 RenderObjectWidget 一族,有着创建和维护 RenderObject 的使命。 FadeTransition#createRenderObject 返回的是 RenderAnimatedOpacity ,也就是说透明动画的功能,是由该类实现的。

可以看出 FadeTransition 只是使用外界传入的属性创建 RenderAnimatedOpacity ,本身非常简单。下面继续看一下 RenderAnimatedOpacity 是如何实现 透明度跟随动画值变化 的。

三、 RenderAnimatedOpacity 源码解读

1. RenderAnimatedOpacity 类

RenderAnimatedOpacity 内只是对成员初始化了一下,什么都没处理。而是混入了 RenderAnimatedOpacityMixin 实现功能。

class RenderAnimatedOpacity extends RenderProxyBox with RenderProxyBoxMixin
 RenderAnimatedOpacityMixin<RenderBox
{

  RenderAnimatedOpacity({
    required Animation<double> opacity,
    bool alwaysIncludeSemantics = false,
    RenderBox? child,
  }) : assert(opacity != null),
       assert(alwaysIncludeSemantics != null),
       super(child) {
    this.opacity = opacity;
    this.alwaysIncludeSemantics = alwaysIncludeSemantics;
  }
}

2. Animation 对象被监听的时机

RenderAnimatedOpacityMixin.attach 方法中,会对 opacity 进行监听,也就是每当 opacityvalue 变化时,会触发 _updateOpacity 方法。

RenderAnimatedOpacityMixin._updateOpacity 中,会通过 opacity 的值更新 _alpha 成员,并通过 markNeedsPaint 触发重绘。

3.RenderAnimatedOpacityMixin#paint 方法

如下是 RenderAnimatedOpacityMixin#paint 的逻辑,可见它和 RenderOpacity 的绘制是一样的。当 child 非空时,如果 _alpha = 0 就什么都不需要画。如果 _alpha = 255 ,则直接绘制 child 。如果有透明度时,会通过 context.pushOpacity 添加 OpacityLayer 透明度层。

这样总的看来 FadeTransition 组件的功能实现还是比较简单的,就是通过监听 Animation 触发透明度更新和重绘。这些都是由 RenderAnimatedOpacity 自主完成的,动画执行的过程中,不涉及到其他 Elememnt 的重建,所以是比较高效的方式。那本文就到这里,谢谢观看 ~