Flutter 平移动画 — 4种实现方式

这篇具有很好参考价值的文章主要介绍了Flutter 平移动画 — 4种实现方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章

  1. Flutter 旋转动画 — RotationTransition
  2. Flutter 平移动画 — 4种实现方式
  3. Flutter 淡入淡出与逐渐出现动画
  4. Flutter 尺寸缩放、形状、颜色、阴影变换动画
  5. Flutter 列表Item动画 — AnimatedList实现Item左进左出、淡入淡出
  6. Flutter Hero 实现共享元素转场动画
  7. Flutter Hero 实现径向变换动画 — 圆形变成矩形的转场动画
  8. Flutter 自定义动画 — 数字递增动画和文字逐行逐字出现或消失动画

1 平移动画效果图

Flutter 平移动画 — 4种实现方式

2 动画基础知识

  • Animation 是 Flutter 动画库中的核心类,它插入用于引导动画的值。
  • AnimationController 管理动画。例如控制动画开始、停止、前进、后退等。
  • CurvedAnimation 将进程定义为非线性曲线。
  • Tween 在被动画对象使用的数据范围之间进行插值。 例如,Tween 可以定义从红色到蓝色或从 0 到 255 的插值。
  • Listeners 和 StatusListeners 可监控动画状态的变化。
  • AnimatedWidget 是展示动画的Widget,Flutter提供一些动画Widget让我们快速实现动画效果。例如:
    AnimatedBuilder、 AnimatedModalBarrier、AlignTransition、DecoratedBoxTransition、FadeTransition、PositionedTransition、RelativePositionedTransition、RotationTransition、ScaleTransition、SizeTransition、SlideTransition

3 平移动画实现方式

Flutter提供了四个Widget可实现平移动画,分别是

  • SlideTransition
  • AlignTransition
  • PositionedTransition
  • RelativePositionedTransition

3.1 SlideTransition

SlideTransition 是基于 Animation<Offset> 来确定平移位置的。平移的具体距离,是由Widget自身的宽高 * Offset中的 x y 值。

例:Widget 的width=100,height = 200,平移动画的起点为Offset(0,0),终点 为Offset(2,3),则平移动画移动的宽度就是 width*dx = 100 *2 ;高度就是 height * dy= 200 *3

3.1.1 实现Widget从左上角平移到右下角

大概步骤:

  1. 创建 AnimationController
  2. 使用 LayoutBuilder 获取到容器的宽高
  3. 通过容器与子控件的宽高 计算出偏移量 Offset
  4. 创建补间动画 Tween<Offset>
  5. 使用 SlideTransition 实现平移动画

具体代码:

  
class SlideTransitionPage extends StatefulWidget {
  const SlideTransitionPage({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _SlideTransitionPageState();
}

class _SlideTransitionPageState extends State<SlideTransitionPage>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;

  @override
  void initState() {
    super.initState();
    /// 重复播放,持续时间为5秒的动画控制器
    _controller = AnimationController(
      duration: const Duration(seconds: 5),
      vsync: this,
    )..repeat(reverse: true);
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          /// 需要平移的Widget 宽高
          const childHeight = 100.0;
          const childWidth = 150.0;

          /// 父布局的宽高
          final parentWidth = constraints.maxWidth;
          final parentHeight = constraints.maxHeight;

          /// 动画起点是左上角
          const startOffset = Offset(0, 0);

          /// 动画终点右下角(父布局宽高 - 子控件宽高)/子控件宽高
          /// 因为平移时子控件大小会占用一部分空间所以需要减去
          final dx = (parentWidth - childWidth) / childWidth;
          final dy = (parentHeight - childHeight) / childHeight;
          final endOffset = Offset(dx, dy);
          
          /// 补间动画
          final offsetAnimation =
              Tween<Offset>(begin: startOffset, end: endOffset)
                  .animate(_controller);

          return SlideTransition(
            position: offsetAnimation,
            child: Container(
              width: childWidth,
              height: childHeight,
              color: Colors.red,
            ),
          );
        },
      ),
    );
  }
}

3.1.2 效果图

Flutter 平移动画 — 4种实现方式


3.2 AlignTransition

如果只是实现 topLeft 、topCenter 、topRight 、centerLeft、center 、centerRight 、bottomLeft、bottomCenter 、bottomRight 这些特殊点位的平移,使用AlignTransition则比较方便。

AlignTransition 是基于 Alignment 来确定平移位置的。

3.2.1 实现Widget从左下角到右上角的非线性平移动画

非线性动画需要使用Curved­Animation

  class AlignTransitionPage extends StatefulWidget {
  const AlignTransitionPage({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _AlignTransitionPageState();
}

class _AlignTransitionPageState extends State<AlignTransitionPage>
    with SingleTickerProviderStateMixin {
  /// 可重复播放 持续时间为5秒
  late final AnimationController _controller = AnimationController(
    duration: const Duration(seconds: 5),
    vsync: this,
  )
    ..repeat(reverse: true);

  /// 左下角 到 右上角
  late final Animation<AlignmentGeometry> _animation = Tween<AlignmentGeometry>(
    begin: Alignment.bottomLeft,
    end: Alignment.topRight,
  ).animate(
    /// 非线性动画,可查看Curves源码,看具体的效果
    CurvedAnimation(
      parent: _controller,
      curve: Curves.easeInCirc,
    ),
  );

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: AlignTransition(
        alignment: _animation,
        child: Container(
          width: 100,
          height: 100,
          color: Colors.red,
        ),
      ),
    );
  }
}

3.2.2 效果图

Flutter 平移动画 — 4种实现方式


3.3 PositionedTransition

PositionedTransition 是基于 RelativeRect 来确定平移位置的。从rect1 平移至 rect2,若Rect大小不一致,则可改变Widget尺寸大小。

PositionedTransition 必须放置在 Stack Widget 中。

RelativeRect:相对于父容器尺寸来确定自身的位置、大小。

3.3.1 实现Widget平移时尺寸也变大缩小

class PositionedTransitionPage extends StatefulWidget {
  const PositionedTransitionPage({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _PositionedTransitionPageState();
}

class _PositionedTransitionPageState extends State<PositionedTransitionPage>
    with SingleTickerProviderStateMixin {

  /// 可重复播放,持续时间为5秒的动画控制器
  late final AnimationController _controller = AnimationController(
    duration: const Duration(seconds: 5),
    vsync: this,
  )..repeat(reverse: true);

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      /// 计算容器的尺寸
      body: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          final Size biggest = constraints.biggest;

          /// 需要平移的Widget 宽高
          const childHeight = 40.0;
          const childWidth = 60.0;

          /// 平移后Widget 变成3倍大小
          const targetChildHeight = childHeight * 3;
          const targetChildWidth = childWidth * 3;

          /// 计算起始位置 左上角 -> 右下角
          /// 根据自身大小,以及父布局大小获取相对位置
          var beginRect = RelativeRect.fromSize(
            const Rect.fromLTWH(0, 0, childWidth, childHeight),
            biggest,
          );

          var endRect = RelativeRect.fromSize(
            Rect.fromLTWH(
              biggest.width - targetChildWidth,
              biggest.height - targetChildHeight,
              targetChildWidth,
              targetChildHeight,
            ),
            biggest,
          );

          /// 补间动画
          final rectAnimation =
              RelativeRectTween(begin: beginRect, end: endRect)
                  .animate(_controller);

          return Stack(
            children: [
              PositionedTransition(
                rect: rectAnimation,
                child: Container(
                  width: childWidth,
                  height: childHeight,
                  color: Colors.red,
                ),
              ),
            ],
          );
        },
      ),
    );
  }
}

3.3.2 效果图

Flutter 平移动画 — 4种实现方式


3.4 RelativePositionedTransition

RelativePositionedTransition 与 PositionedTransition类似,只是RelativePositionedTransition需要传参父容器的尺寸以及平移起始位置,它帮我们计算RelativeRect。

RelativePositionedTransition 必须放置在 Stack Widget 中。

RelativePositionedTransition 基于 Rect 与 Size 确定平移位置

3.4.1 实现Widget位置平移、尺寸变换的非曲线动画

class RelativePositionedTransitionPage extends StatefulWidget {
  const RelativePositionedTransitionPage({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _RelativePositionedTransitionPageState();
}

class _RelativePositionedTransitionPageState extends State<RelativePositionedTransitionPage>
    with SingleTickerProviderStateMixin {
  /// 可重复播放,持续时间为5秒的动画控制器
  late final AnimationController _controller = AnimationController(
    duration: const Duration(seconds: 5),
    vsync: this,
  )..repeat(reverse: true);

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      /// 计算容器的尺寸
      body: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          final Size biggest = constraints.biggest;

          /// 需要平移的Widget 宽高
          const childHeight = 40.0;
          const childWidth = 60.0;

          /// 平移后Widget 变成3倍大小
          const targetChildHeight = childHeight * 3;
          const targetChildWidth = childWidth * 3;

          /// 计算起始位置 左上角 -> 右下角
          var beginRect = const Rect.fromLTWH(0, 0, childWidth, childHeight);
          var endRect = Rect.fromLTWH(
            biggest.width - targetChildWidth,
            biggest.height - targetChildHeight,
            targetChildWidth,
            targetChildHeight,
          );

          /// 补间动画
          final rectAnimation =
              RectTween(begin: beginRect, end: endRect).animate(
            CurvedAnimation(
              parent: _controller,
              curve: Curves.easeInCirc,
            ),
          );

          return Stack(
            children: [
              RelativePositionedTransition(
                rect: rectAnimation,
                size: biggest,
                child: Container(
                  width: childWidth,
                  height: childHeight,
                  color: Colors.red,
                ),
              ),
            ],
          );
        },
      ),
    );
  }
}

3.4.2 效果图

Flutter 平移动画 — 4种实现方式文章来源地址https://www.toymoban.com/news/detail-416253.html

到了这里,关于Flutter 平移动画 — 4种实现方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Flutter系列文章-Flutter进阶2

    这一节我将再详细地为您介绍 Flutter 进阶主题,包括导航和路由、状态管理、异步处理、HTTP请求和Rest API,以及数据持久化。让我们逐个介绍这些主题。 在 Flutter 中,导航和路由是构建多页面应用的关键概念。导航是指从一个页面(或称为路由)切换到另一个页面的过程。每

    2024年02月15日
    浏览(43)
  • Flutter系列文章-Flutter UI进阶

    在本篇文章中,我们将深入学习 Flutter UI 的进阶技巧,涵盖了布局原理、动画实现、自定义绘图和效果、以及 Material 和 Cupertino 组件库的使用。通过实例演示,你将更加了解如何创建复杂、令人印象深刻的用户界面。 Row 和 Column 是常用的布局组件,但灵活地使用它们可以带来

    2024年02月13日
    浏览(36)
  • Flutter系列文章-实战项目

    在本篇文章中,我们将通过一个实际的 Flutter 应用来综合运用最近学到的知识,包括保存到数据库、进行 HTTP 请求等。我们将开发一个简单的天气应用,可以根据用户输入的城市名获取该城市的天气信息,并将用户查询的城市列表保存到本地数据库中。 1. 确定项目目标 我们

    2024年02月13日
    浏览(35)
  • Flutter系列文章-Flutter环境搭建和Dart基础

    Flutter是Google推出的一个开源的、高性能的移动应用开发框架,可以用一套代码库开发Android和iOS应用。Dart则是Flutter所使用的编程语言。让我们来看看如何搭建Flutter开发环境,并了解Dart语言的基础知识。 1. 安装Flutter SDK 首先,访问Flutter官网下载Flutter SDK。选择适合你操作系统

    2024年02月15日
    浏览(49)
  • flutter系列之:如何自定义动画路由

    目录 简介 自定义跳转使用 flutter动画基础 实现一个自定义的route 总结 flutter中有默认的Route组件,叫做MaterialPageRoute,一般情况下我们在flutter中进行跳转的话,只需要向Navigator中传入一个MaterialPageRoute就可以了。 但是MaterialPageRoute太普通了,如果我们想要做点不同的跳转特效

    2023年04月19日
    浏览(46)
  • Flutter系列文章-Flutter在实际业务中的应用

    1. 跨平台开发: 在移动应用开发中,面对不同的平台(iOS和Android),我们通常需要编写两套不同的代码。而Flutter通过一套代码可以构建适用于多个平台的应用,大大提高了开发效率,降低了维护成本。 2. 混合开发: 在一些已有的原生应用中,引入Flutter可以用于开发某些特

    2024年02月11日
    浏览(44)
  • flutter系列之:做一个下载按钮的动画

    目录 简介 定义下载的状态 定义DownloadButton的属性 让DownloadButton的属性可以动态变化 定义downloadController 定义DownloadButton的细节 总结 我们在app的开发过程中经常会用到一些表示进度类的动画效果,比如一个下载按钮,我们希望按钮能够动态显示下载的进度,这样可以给用户一

    2024年02月06日
    浏览(39)
  • flutter系列之:做一个修改组件属性的动画

    目录 简介 flutter中的动画widget AnimatedContainers使用举例 总结 什么是动画呢?动画实际上就是不同的图片连续起来形成的。flutter为我们提供了一个AnimationController来对动画进行详尽的控制,不过直接是用AnimationController是比较复杂的,如果只是对一个widget的属性进行修改,可以做

    2024年02月03日
    浏览(63)
  • flutter系列之:使用AnimationController来控制动画效果

    目录 简介 构建一个要动画的widget 让图像动起来 总结 之前我们提到了flutter提供了比较简单好用的AnimatedContainer和SlideTransition来进行一些简单的动画效果,但是要完全实现自定义的复杂的动画效果,还是要使用AnimationController。 今天我们来尝试使用AnimationController来实现一个拖

    2024年02月05日
    浏览(39)
  • 使用C#的窗体显示与隐藏动画效果方案 - 开源研究系列文章

    今天继续研究C#的WinForm的显示动画效果。 上次我们实现了无边框窗体的显示动画效果(见博文:基于C#的无边框窗体动画效果的完美解决方案 - 开源研究系列文章 ),这次介绍的是未在任务栏托盘中窗体的显示隐藏动画效果的实现代码。 1、 项目目录; 下面是项目目录,由基本

    2024年02月14日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包