Flutter 中各种单属性动画组件的使用(一)|周末学习

这是我参与更文挑战的第5天,活动详情查看: 更文挑战
本文已参与 周末学习计划,点击查看详情

前言

上一篇我们聊了 Flutter 中最常用的 Widget Container 对应的动画组件 AnimatedContainer ,它的很多属性都可以在值发生变化的时候以动画的方式转换。
如果我们只想对单个属性比如 padding 来设置的话,嵌套一个 AnimatedContainer 就显的有些**笨重,**还有在 Stack 中我们要使用绝对定位时也是无法优雅实现的。
这一篇我们就来聊聊 Flutter 中的几个「单属性动画组件」。

AnimatedPadding (动画边距)

01.gif
这个 Widget 与 AnimatedContainer 中的 padding 属性类似,只需要我们设置一个 durationpadding 即可,单独使用嵌套在我们自定义的组件上是非常方便的。

/// 属性
var height = 100.0;
Duration duration = Duration(milliseconds: 300);
var padding = 0.0;
// 设置
GestureDetector(
  onTap: () {
		// 点击改变边距
    this.padding = padding == 0 ? 30 : 0;
    setState(() {});
  },
  child: AnimatedPadding(
    duration: duration,
    curve: Curves.easeIn,
    // 设置边距
    padding: EdgeInsets.all(padding),
    child: DescContainer(
      height: height,
      width: width,
      color: Colors.blue,
      text: 'AnimatedPadding',
    ),
  ),
)
复制代码

自定义通用 DescContainer

这个是我们抽离的通用描述容器组件,为了之后我们复用,项目中也建议大家把通用的 Widget 抽离成单独的组件来使用,通常需要扩展时增加属性即可。

/// 通用描述容器
class DescContainer extends StatelessWidget {
  const DescContainer({
    Key? key,
    required this.color,
    required this.height,
    required this.width,
    required this.text,
  }) : super(key: key);
  // 背景颜色
  final Color color;
  // 宽度
  final double width;
  // 高度
  final double height;
  // 文字
  final String text;

  @override
  Widget build(BuildContext context) {
    return Container(
      color: color,
      height: height,
      width: width,
      alignment: Alignment.center,
      child: Text(
        text,
        style: TextStyle(
          color: Colors.white,
        ),
      ),
    );
  }
}
复制代码

AnimatedAlign (动画对齐)

上一篇中我们在 AnimatedContainer 中通过设置 alignment 属性来改变 Text 的对齐,这里 Flutter 为我们单独写了一个方便我们使用。
02.gif

/// 属性
var alignment = Alignment.center;
GestureDetector(
  onTap: () {
    var x = Random.secure().nextInt(3);
    var y = Random.secure().nextInt(3);
    // Alignment 设置对齐方式是由 [-1、0、1] 设置 x 和 y 来组成的
    this.alignment = Alignment(x - 1, y - 1);
    setState(() {});
  },
  // 背景
  child: Container(
    height: 200,
    color: Colors.grey[350],
    child: AnimatedAlign(
      // 设置对齐方式
      alignment: alignment,
      duration: duration,
      child: DescContainer(
        height: 60,
        width: 180,
        color: Colors.amber,
        text: 'AnimatedAlign',
      ),
    ),
  ),
)
复制代码

Alignment 对齐方式(一起看源码)

这里我们扩展一下,看看源码中 Alignment 是怎么实现的。

// Alignment 类继承自 AlignmentGeometry
class Alignment extends AlignmentGeometry {
  const Alignment(this.x, this.y)
    : assert(x != null),
      assert(y != null);
  final double x;
  final double y;
  static const Alignment topLeft = Alignment(-1.0, -1.0);
  ...
  static const Alignment center = Alignment(0.0, 0.0);
  ...
  static const Alignment bottomRight = Alignment(1.0, 1.0);
  ...
}
复制代码

这里可以看到 Alignment 就是由 x、y 两个属性组成的类,其中 x 和 y 的值是 [-1,0,1] 分别表示如下:

  • x:[-1,0,1] :[左,中,右]
  • y:[-1,0,1] :[上,中,下]

也可以看到 topLeft、center、bottomRight 等这些我们经常使用的常量是由 x、y 的 [-1,0,1] 组成

AnimatedPositioned(定位动画)

在项目中也经常会使用到 Stack,然后通过给 子 Widget 嵌套一个 Positioned 来实现子组件的定位布局,如果要加上动画我们使 AnimatedPositioned 即可,来看看效果。
03.gif

/// 这里我们就不贴全部代码了
/// 点击改变左上右下距离
onTap: () {
  this.top = top == 0 ? 20 : 0;
  this.left = left == 0 ? 30 : 0;
  this.right = right == 0 ? 40 : 0;
  this.bottom = bottom == 0 ? 80 : 0;
  setState(() {});
}
Stack(
  fit: StackFit.expand,
  children: [
    AnimatedPositioned(
      // 设置动画时长
      duration: duration,
      // 设置动画曲线
      curve: Curves.decelerate,
      // 设置定位左上
      top: top,
      left: left,
      child: DescContainer(
        height: 60,
        width: 180,
        color: Colors.cyan,
        text: 'AnimatedPositioned',
      ),
    ),
    AnimatedPositioned(
      duration: duration,
      curve: Curves.decelerate,
      // 设置定位右下
      right: right,
      bottom: bottom,
      child: DescContainer(
        height: 60,
        width: 180,
        color: Colors.amber,
        text: 'AnimatedPositioned',
      ),
    ),
  ],
)
复制代码

AnimatedOpacity(动画不透明)

如果你想要透明度改变时也有一个动画效果,那么可以使用这个 Widget,只需要设置 opacity 不透明度即可,一般在过渡动画时使用效果非常好。
04.gif

GestureDetector(
  onTap: () {
    // 点击切换改变透明度,
    this.opacity = opacity == 1 ? 0.5 : 1;
    setState(() {});
  },
  child: AnimatedOpacity(
    // 设置透明度
    opacity: opacity,
    // 设置动画时长
    duration: duration,
    // 设置动画曲线
    curve: Curves.easeOut,
    child: DescContainer(
      height: 60,
      width: 300,
      color: Colors.purple,
      text:
      'AnimatedOpacity opacity:${opacity.toStringAsFixed(2)}',
    ),
  ),
)
复制代码

范围

  • 范围是 0.0~1.0
  • 1:完全不透明
  • 0:完全透明

源码仓库

基于 Flutter ? 最新版本

参考链接

关注专栏

  • 此文章已收录到下面? 的专栏,可以直接关注
  • 更多文章继续阅读|系列文章持续更新

? 欢迎点赞➕收藏➕关注,有任何问题随时在下面?评论,我会第一时间回复哦

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享