写点什么

Flutter 动画组件那么多,记不住不会用怎么办?我都给你整理好了,收藏吧!

作者:岛上码农
  • 2022 年 8 月 15 日
    湖南
  • 本文字数:4254 字

    阅读完需:约 14 分钟

Flutter 动画组件那么多,记不住不会用怎么办?我都给你整理好了,收藏吧!

前言

Flutter 自带的基础动画组件称之为隐式动画组件,小小统计了一下,会有几十个那么多,包括通用的动画构建类、特定的动画效果类以及封装好的动画组件。这么多,好处是想用的基本都有,不好的地方是记不住,找起来也不太方便。本篇特地整理了 Flutter 的隐式动画组件,方便各位 Flutter 爱好者(搬砖者)随时查看和使用。

AnimatedWidget

AnimatedWidget 是一个抽象类,可以通过 Animation 对象的值动态刷新每一帧从而实现动画效果。如果你想构建自己可复用的动画组件,那么可以使用 AnimatedWidget,我们在大风车吱呀吱哟哟地转,这个风车加载指示组件真有趣!Flutter 构建三维空间动画效果这两篇文章中就使用了AnimatedWidget构建了一个风车加载指示动画组件。AnimatedWidget 的构造方法如下,其中 listenable 是一个抽象类 Listenable 对象,一般是 AnimationChangeNotifier


const AnimatedWidget({  Key? key,  required this.listenable,}) 
复制代码

Animation

Animation 不算是一个组件,但是构建隐式动画组件都需要 Animation 对象来控制动画起止参数,动画曲线等。借助 Animation,你可以基于 StatefulWidgetStatelessWidget 构建自己的动画类。我们在Flutter 实现爱心三连动画效果使用了 Animation 构建了爱心尺寸变化的动画。Animation 通常是依赖 AnimationController 组合实现动画效果。

AnimatedBuilder

AnimatedBuilder 将动画效果和组件分离,从而使得动效可以应用与不同组件。如果在应用中一个动效会被用于多个不同的组件,那么 AnimatedBuilder 是首选。我们在用 AnimatedBuilder 分离组件和动画,实现动效复用​做了AnimatedBuilder的示例应用。AnimatedBuilder 的构造方法如下,animationbuilder 是外部传入的,因此可以构造与组件分离的可复用的动画效果。


const AnimatedBuilder({    Key? key,    required Listenable animation,    required this.builder,    this.child,  }) 
复制代码

AnimatedContainer

AnimatedContainerContainer 的动画替换组件,可以通过修改动画过程中的尺寸、对齐方式,tranform 参数等实现容器的动画效果。我们使用了 AnimatedContainer 实现了一个笑脸动画:Flutter 来一个笑嘻嘻的动态表情AnimatedContainer的构造方法如下,可以看到基本上所有的布局相关的属性都可以受动效控制。


AnimatedContainer({  Key? key,  this.alignment,  this.padding,  Color? color,  Decoration? decoration,  this.foregroundDecoration,  double? width,  double? height,  BoxConstraints? constraints,  this.margin,  this.transform,  this.transformAlignment,  this.child,  this.clipBehavior = Clip.none,  Curve curve = Curves.linear,  required Duration duration,  VoidCallback? onEnd,})
复制代码

AnimatedPositioned

AnimatedPositionedStack 组件中的 Positioned 的动画替换组件。可以通过 AnimatedPositioned 实现组件在 Stack 组件的位置,从而实现相对 Stack 组件的移动效果,譬如:Flutter 模拟火箭发射动画AnimatedPositioned的构造方法如下,需要注意的是横向参数(leftrightwidth)、纵向参数(topbottomheight)只能从 3 个里面选 2 个设置,否则会导致布局冲突。


const AnimatedPositioned({  Key? key,  required this.child,  this.left,  this.top,  this.right,  this.bottom,  this.width,  this.height,  Curve curve = Curves.linear,  required Duration duration,  VoidCallback? onEnd,})
复制代码

AnimatedCrossFade

AnimatedCrossFade 用于两个组件切换,动效是渐现效果。同时若两个子组件的尺寸不同,可以使用 layoutBuilder 来平滑过渡尺寸的变化。两个子组件的动画曲线可以单独配置。最简单的应用就是更改两个要切换的子组件的显示,代码如下所示:


AnimatedCrossFade(  duration: const Duration(seconds: 3),  firstChild: const FlutterLogo(style: FlutterLogoStyle.horizontal, size: 100.0),  secondChild: const FlutterLogo(style: FlutterLogoStyle.stacked, size: 100.0),  crossFadeState: _first ? CrossFadeState.showFirst : CrossFadeState.showSecond,)
复制代码


AnimatedCrossFade 的构造方法如下,其中 layoutBuilder 默认的组件布局构建方法。


const AnimatedCrossFade({  Key? key,  required this.firstChild,  required this.secondChild,  this.firstCurve = Curves.linear,  this.secondCurve = Curves.linear,  this.sizeCurve = Curves.linear,  this.alignment = Alignment.topCenter,  required this.crossFadeState,  required this.duration,  this.reverseDuration,  this.layoutBuilder = defaultLayoutBuilder,})
复制代码

AnimatedDefaultTextStyle

AnimatedDefaultTextStyle 用于文字样式动画效果,如果想自己控制字体变化过程(比如停留在中中间状态),可以使用DefaultTextStyleTransition 来完成。下面的动图是官网的效果,利用字体过渡的动画可以做品牌文字类的动画,可以加深用户的印象。



AnimatedDefaultTextStyle 的构造方法如下。


const AnimatedDefaultTextStyle({  Key? key,  required this.child,  required this.style,  this.textAlign,  this.softWrap = true,  this.overflow = TextOverflow.clip,  this.maxLines,  this.textWidthBasis = TextWidthBasis.parent,  this.textHeightBehavior,  Curve curve = Curves.linear,  required Duration duration,  VoidCallback? onEnd,})
复制代码

AnimatedList

AnimatedList 借助 AnimatedListState 可以实现插入和移出元素时的动画过渡效果,从而给列表的元素增加和删除的操作带来更好的反馈,提升用户体验。我们在 还在用 ListView?使用 AnimatedList 让列表元素动起来中介绍了如何使用 AnimatedList。 整个的实现来说还是有点复杂,推荐在列表元素不多的时候使用。AnimatedList 的构造方法如下,其中关键的是 itemBuilder 接收了一个 animation 对象,因此可以用来完成插入动画。而对于删除元素,则需要借助 AnimatedListStateremoveItem 方法完成。


const AnimatedList({  Key? key,  required this.itemBuilder,  this.initialItemCount = 0,  this.scrollDirection = Axis.vertical,  this.reverse = false,  this.controller,  this.primary,  this.physics,  this.shrinkWrap = false,  this.padding,  this.clipBehavior = Clip.hardEdge,})
复制代码

AnimatedModalBarrier

AnimatedModelBarrierModalBarrier 的替换,可以挡住它下层的组件,使得这些组件无法与用户交互,并且在组件上加一层颜色动画过渡遮罩。AnimatedModelBarrier 的构造方法如下。其中 dismissible 参数如果为 true,则点击遮罩时会退出当前页面返回到上一页。


const AnimatedModalBarrier({  Key? key,  required Animation<Color?> color,  bool dismissible,  String? semanticsLabel,  bool? barrierSemanticsDismissible})
复制代码


可以使用AnimatedModalBarrier 做自定义弹层,当要弹出弹层时,使用 AnimatedModalBarrier 遮挡底层,然后再在它上层叠加新的组件就可以实现弹层的效果。下面是我们实现的一个示例,点击按钮后弹出一个遮罩层,然后遮罩上加了一个文字层。


AnimatedOpacity

AnimatedOpacity 是透明度控制动画,可以控制子组件的透明度。这个就很好理解了,在动画过程中更改组件透明度。我们在Flutter 实现小姐姐渐现动画效果 已经有过介绍了。

AnimatedPhysicalModel

控制组件的阴影、颜色、边框圆弧等物理模型,但组件自身的形状不发生改变。比如下图是官方给了一个更改阴影的例子,虽然组件自己没有变,但是因为阴影的变化,感觉却像是推开了一道缝隙一样,也挺有趣的。



AnimatedPhysicalModel 的构造方法如下,其中颜色和阴影颜色是通过两个布尔值 animateColoranimateShadowColor 决定是否要通过动画显示的。


const AnimatedPhysicalModel({  Key? key,  required Widget child,  required BoxShape shape,  Clip clipBehavior,  BorderRadius borderRadius,  required double elevation,  required Color color,  bool animateColor,  required Color shadowColor,  bool animateShadowColor,  Curve curve = Curves.linear,  required Duration duration,  VoidCallback? onEnd})
复制代码


下面是一段示例代码,通过更改elevation 属性实现 Z 轴阴影的变化,同时做了颜色的过渡动画效果:


Widget build(BuildContext context) {  return Scaffold(    appBar: AppBar(      title: Text('AnimatedPhysicalModel 动画'),    ),    body: Center(      child: AnimatedPhysicalModel(        child: Container(          width: 300,          height: 300,        ),        duration: Duration(seconds: 1),        color: _elevation == 0.0 ? Colors.blue : Colors.green,        animateColor: true,        animateShadowColor: true,        elevation: _elevation,        shape: BoxShape.circle,        shadowColor: Colors.blue[900]!,        curve: Curves.easeInOutCubic,      ),    ),    floatingActionButton: FloatingActionButton(      child: Text(        'Play',        style: TextStyle(          color: Colors.white,        ),        textAlign: TextAlign.center,      ),      onPressed: () {        setState(() {          _elevation = _elevation == 0 ? 10.0 : 0.0;        });      },    ),  );}
复制代码

AnimatedSize

子组件的尺寸变化动画组件,通过尺寸的改变可以做放大缩小的效果,下面是官方的一个示例,点击组件的时候更改组件的尺寸,感觉是缩放一样。


Widget build(BuildContext context) {  return GestureDetector(    onTap: () => _updateSize(),    child: Container(      color: Colors.amberAccent,      child: AnimatedSize(        curve: Curves.easeIn,        duration: const Duration(seconds: 1),        child: FlutterLogo(size: _size),      ),    ),  );}
复制代码

总结

本篇列举了 Flutter 隐式动画的 12 个基础组件,普通的动画效果依赖这些组件基本就能搞定了。而如果需要转换类的动画效果需要使用 Transition 来支持,下篇岛上码农为你整理一下 Transition 类的动画组件。源码可以到这里下载:动画组件演示示例源码


发布于: 刚刚阅读数: 4
用户头像

岛上码农

关注

用代码连接孤岛,公众号@岛上码农 2022.03.03 加入

从南漂到北,从北漂到南的业余码农

评论

发布
暂无评论
Flutter 动画组件那么多,记不住不会用怎么办?我都给你整理好了,收藏吧!_flutter_岛上码农_InfoQ写作社区