12

Flutter 组件 | AnimatedOpacity 透明动画

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzI0NjU3MDA4NQ%3D%3D&%3Bmid=2247484555&%3Bidx=1&%3Bsn=3c77782eb8df8af034360efe5fc99a0e
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、认识 AnimatedOpacity 组件

1. AnimatedOpacity 基本信息

AnimatedOpacity 作为一个 StatefulWidget ,说明它的核心功能会借助其他组件实现,自身承担更新组件状态的任务。 AnimatedOpacity 是 隐式动画 ImplicitlyAnimatedWidget 族的一员,该族实现的动画无须指定动画器,更方便用户使用。

NVNNfqI.png!mobile

2. AnimatedOpacity 的使用

AnimatedOpacity 需要一个 double 类型的参数 opacity ,每当 opacity 变化时,child 就会 从旧值到新值 进行透明渐变。为了改变 opacity ,需要外界的触发刷新,最常用的是 State#setState 。注意:这里只是在按钮点击的时候触发的 setState 一次,这和 监听动画器来触发 setState 是不一样的。

child 组件进行动画变化是被封装在 AnimatedOpacity 内部的,不会造成当前 _FadeTransitionTestState 的频繁 build ,只构建一次其实并没有多大的影响。

BbaAZjN.gif!mobile

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

class _FadeTransitionTestState extends State<FadeTransitionTest{
  double opacity = 1.0;

  void _changeOpacity() {
    setState(() => opacity = opacity == 0 ? 1.0 : 0.0);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        AnimatedOpacity(
          opacity: opacity,
          duration: const Duration(seconds: 2),
          child: buildContent(),
        ),
        ElevatedButton(
          child: const Text('执行动画'),
          onPressed: _changeOpacity,
        ),
      ],
    );
  }

  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),
        ),
      ],
    );
  }
}

当然如果你实在不想 setState ,可以用 ValueListenableBuilder ,只要能改变 AnimatedOpacityopacity 属性,就可以进行动画。你有么有想过,为什么 AnimatedOpacity 可以不通过动画控制器,就可以让 child 组件进行动画?接下来,一起来探索吧。

二、 AnimatedOpacity 源码解读

1. AnimatedOpacity 组件属性

AnimatedOpacity 继承自 ImplicitlyAnimatedWidgetAnimatedOpacity 的属性如下:

属性 介绍 类型 默认值 child 子组件 Widget null opacity 透明度 double @require duration 动画时长 Duration @require onEnd 动画结束回调 VoidCallback null curve 动画曲线 Curve Curves.linear nYjiuu.png!mobile

2.ImplicitlyAnimatedWidget 组件

ImplicitlyAnimatedWidget 是抽象类继承自 StatefulWidget ,其中定义了动画相关的属性。抽象方法为 createState ,返回一个泛型是 ImplicitlyAnimatedWidget 的   ImplicitlyAnimatedWidgetState 对象。

F3aEBz.png!mobile

3.ImplicitlyAnimatedWidgetState 状态类

ImplicitlyAnimatedWidgetState 是实现动画的关键,它是一个抽象类,其中维护了 AnimationController 并进行动画状态的监听。

bMfUvmB.png!mobile

4. _AnimatedOpacityState 状态类

AnimatedOpacity 对应的 State_AnimatedOpacityState ,其构建依赖于 FadeTransition 。上一篇已经介绍了FadeTransition 组件 实现的原理,这里就不赘述了。

jiy2e2y.png!mobile

5.重设值更新

opacity 值重设,并触发重建时, didUpdateWidget 会触发。其中 _controller 会执行动画,这也是为什么重设 opacity 值 child 会执行动画的原因。至于 ImplicitlyAnimatedWidget 的更多细节,将会在之后的文章中慢慢诉说。

nQbem2V.png!mobile

这样看来 AnimatedOpacity 功能的实现本质上是 FadeTransition 组件的功劳。 AnimatedOpacity 存在的价值是,内部维护着动画控制器,无须用户处理动画的相关逻辑,使用更为方便。但反之,由于用户无法对控制器进行操作,灵活性降低。根据场景合理使用 AnimatedOpacityFadeTransition ,这两个都是实现透明渐变非常优秀的组件。那本篇就到这里,谢谢观看 ~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK