系列文章

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

文章目录

  • 系列文章
  • 1 平移动画效果图
  • 2 动画基础知识
  • 3 平移动画实现方式
    • 3.1 SlideTransition
      • 3.1.1 实现Widget从左上角平移到右下角
      • 3.1.2 效果图
    • 3.2 AlignTransition
      • 3.2.1 实现Widget从左下角到右上角的非线性平移动画
      • 3.2.2 效果图
    • 3.3 PositionedTransition
      • 3.3.1 实现Widget平移时尺寸也变大缩小
      • 3.3.2 效果图
    • 3.4 RelativePositionedTransition
      • 3.4.1 实现Widget位置平移、尺寸变换的非曲线动画
      • 3.4.2 效果图

1 平移动画效果图

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);@overrideState<StatefulWidget> createState() => _SlideTransitionPageState();
}class _SlideTransitionPageState extends State<SlideTransitionPage>with SingleTickerProviderStateMixin {late final AnimationController _controller;@overridevoid initState() {super.initState();/// 重复播放,持续时间为5秒的动画控制器_controller = AnimationController(duration: const Duration(seconds: 5),vsync: this,)..repeat(reverse: true);}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget 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 效果图


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);@overrideState<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,),);@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(body: AlignTransition(alignment: _animation,child: Container(width: 100,height: 100,color: Colors.red,),),);}
}

3.2.2 效果图


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);@overrideState<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);@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget 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 效果图


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);@overrideState<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);@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget 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种实现方式相关推荐

  1. css卷轴动画小程序,微信小程序动画两种实现方式

    开发小程序,实现动画功能,有两种实现方式,下面来看看具体怎么做: JS动画 利用小程序API提供的wx.createAnimation(OBJECT)实现,API中是这样说:创建一个动画实例anima ...

  2. Android 图片旋转动画两种实现方式

    说明: 让图片旋转两种方法,使用xml和代码 xml加载: xml布局:anim_rotate.xml <?xml version="1.0" encoding=" ...

  3. Flutter 自定义动画 — 数字递增动画和文字逐行逐字出现或消失动画

    系列文章 Flutter 旋转动画 - RotationTransition Flutter 平移动画 - 4种实现方式 Flutter 淡入淡出与逐渐出现动画 Flutter 尺寸缩放.形状.颜色. ...

  4. flutter SlideTransition实现平移动画

    志在巅峰的攀登者,不会陶醉在沿途的某个脚印之中,在码农的世界里,优美的应用体验,来源于程序员对细节的处理以及自我要求的境界,年轻人也是忙忙碌碌的码农中一员,每天.每周,都会留下一些脚印,就是这些创作的 ...

  5. android旋转动画的两种实现方式

    在android开发,我们会常常使用到旋转动画,普通情况下旋转动画有两种实现方式,一种是直接通过java代码去实现,第二种是通过配置文件实现动画.以下是两种动画的基本是用法: 纯Java代码实现: / ...

  6. android 动画方式,Android Activity进出动画三种方法

    Android Activity进出动画三种方法 实现activity的进出场动画总共有3种方式,下面会一一列出,首先给出示例的动画xml文件. 动画的xml文件 android:fromYDelta ...

  7. HTML5实现动画三种方式

    HTML5实现动画三种方式 编者注:作者以一个运动的小车为例子,讲述了三种实现HTML5动画的方式,思路清晰,动画不仅仅是Canvas,还有css3和javascript.通过合理的选择,来实现最优的 ...

  8. html5生日福利页面,福利到!HTML5实现动画两种方式

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 正在学习或者自学html5的小伙伴,是不是有的已经让video动画整疯掉了呢?哈哈!下面华清远见的小编就为大家两种实现方式!好好学习哦! (1) canv ...

  9. html5 小车动画_HTML5实现动画三种方式

    编者注:作者以一个运动的小车为例子,讲述了三种实现HTML5动画的方式,思路清晰,动画不仅仅是canvas,还有css3和javascript.通过合理的选择,来实现最优的实现. PS:由于显卡.录制 ...

最新文章

  1. 知识产权一般都具有法定的保护期限,一旦保护期限届满,权利将自行终止,成为社会公众可以自由使用的知识。 (20答案:D
  2. DIV+CSS如何设置字体间距
  3. 经典C语言程序100例之二八
  4. java 程序中打开文件和文件夹
  5. QT之深入理解QThread
  6. 《scikit-learn》数据预处理与特征工程(三)特征选择
  7. 关于打开sdk下载不了的最优秀解决方式
  8. spring单元测试无法注入bean_Spring容器启动@Value属性无法注入?
  9. javascript DOM对象转jquery对象
  10. IBM之alphablox + tomcat 安装小记
  11. 125、什么是核心交换机的链路聚合、冗余、堆叠、热备份
  12. 百度网盘机器人软件工具自动发货管理文件好友群补发文件资料 (可用于拼多多淘宝闲鱼虚拟店商品自动发货)
  13. 自动打卡python脚本_[python][企业微信]企业微信自动打卡Python脚本,价值一万元的自动打卡脚本...
  14. 计算机属性资源管理器已停止工作,windows资源管理器已停止工作,教您windows资源管理器已停止工作如何解决...
  15. 天球坐标系和地球坐标系
  16. 知道2020年计算机二级考试成绩,2020年9月计算机二级考试成绩可以查了 多少分及格...
  17. java归并排序算法
  18. 手Q体验不满意的地方之(3)——个人设置栏
  19. [百家争鸣]LYT演讲:人文素养的必要
  20. springboot项目在测试文件夹报空指针异常

热门文章

  1. Java返回Json文件
  2. 为Repository添加自定义方法
  3. 有关关键路径的概念和算法
  4. 生活中的数学:买几送几
  5. mysql cast()与convert() 函数
  6. 程序员杂志在线阅读 豆瓣的架构—专访豆瓣网站的技术总监洪强宁
  7. 基于灰度质心法和骨架的激光中心线提取
  8. Settings学习
  9. Win10 Chinese输入法修复/note
  10. 30岁的我应该何去何从