Flutter 平移动画 — 4种实现方式
系列文章
- Flutter 旋转动画 — RotationTransition
- Flutter 平移动画 — 4种实现方式
- Flutter 淡入淡出与逐渐出现动画
- Flutter 尺寸缩放、形状、颜色、阴影变换动画
- Flutter 列表Item动画 — AnimatedList实现Item左进左出、淡入淡出
- Flutter Hero 实现共享元素转场动画
- Flutter Hero 实现径向变换动画 — 圆形变成矩形的转场动画
- 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从左上角平移到右下角
大概步骤:
- 创建 AnimationController
- 使用 LayoutBuilder 获取到容器的宽高
- 通过容器与子控件的宽高 计算出偏移量 Offset
- 创建补间动画 Tween<Offset>
- 使用 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从左下角到右上角的非线性平移动画
非线性动画需要使用CurvedAnimation
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种实现方式相关推荐
- css卷轴动画小程序,微信小程序动画两种实现方式
开发小程序,实现动画功能,有两种实现方式,下面来看看具体怎么做: JS动画 利用小程序API提供的wx.createAnimation(OBJECT)实现,API中是这样说:创建一个动画实例anima ...
- Android 图片旋转动画两种实现方式
说明: 让图片旋转两种方法,使用xml和代码 xml加载: xml布局:anim_rotate.xml <?xml version="1.0" encoding=" ...
- Flutter 自定义动画 — 数字递增动画和文字逐行逐字出现或消失动画
系列文章 Flutter 旋转动画 - RotationTransition Flutter 平移动画 - 4种实现方式 Flutter 淡入淡出与逐渐出现动画 Flutter 尺寸缩放.形状.颜色. ...
- flutter SlideTransition实现平移动画
志在巅峰的攀登者,不会陶醉在沿途的某个脚印之中,在码农的世界里,优美的应用体验,来源于程序员对细节的处理以及自我要求的境界,年轻人也是忙忙碌碌的码农中一员,每天.每周,都会留下一些脚印,就是这些创作的 ...
- android旋转动画的两种实现方式
在android开发,我们会常常使用到旋转动画,普通情况下旋转动画有两种实现方式,一种是直接通过java代码去实现,第二种是通过配置文件实现动画.以下是两种动画的基本是用法: 纯Java代码实现: / ...
- android 动画方式,Android Activity进出动画三种方法
Android Activity进出动画三种方法 实现activity的进出场动画总共有3种方式,下面会一一列出,首先给出示例的动画xml文件. 动画的xml文件 android:fromYDelta ...
- HTML5实现动画三种方式
HTML5实现动画三种方式 编者注:作者以一个运动的小车为例子,讲述了三种实现HTML5动画的方式,思路清晰,动画不仅仅是Canvas,还有css3和javascript.通过合理的选择,来实现最优的 ...
- html5生日福利页面,福利到!HTML5实现动画两种方式
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 正在学习或者自学html5的小伙伴,是不是有的已经让video动画整疯掉了呢?哈哈!下面华清远见的小编就为大家两种实现方式!好好学习哦! (1) canv ...
- html5 小车动画_HTML5实现动画三种方式
编者注:作者以一个运动的小车为例子,讲述了三种实现HTML5动画的方式,思路清晰,动画不仅仅是canvas,还有css3和javascript.通过合理的选择,来实现最优的实现. PS:由于显卡.录制 ...
最新文章
- 知识产权一般都具有法定的保护期限,一旦保护期限届满,权利将自行终止,成为社会公众可以自由使用的知识。 (20答案:D
- DIV+CSS如何设置字体间距
- 经典C语言程序100例之二八
- java 程序中打开文件和文件夹
- QT之深入理解QThread
- 《scikit-learn》数据预处理与特征工程(三)特征选择
- 关于打开sdk下载不了的最优秀解决方式
- spring单元测试无法注入bean_Spring容器启动@Value属性无法注入?
- javascript DOM对象转jquery对象
- IBM之alphablox + tomcat 安装小记
- 125、什么是核心交换机的链路聚合、冗余、堆叠、热备份
- 百度网盘机器人软件工具自动发货管理文件好友群补发文件资料 (可用于拼多多淘宝闲鱼虚拟店商品自动发货)
- 自动打卡python脚本_[python][企业微信]企业微信自动打卡Python脚本,价值一万元的自动打卡脚本...
- 计算机属性资源管理器已停止工作,windows资源管理器已停止工作,教您windows资源管理器已停止工作如何解决...
- 天球坐标系和地球坐标系
- 知道2020年计算机二级考试成绩,2020年9月计算机二级考试成绩可以查了 多少分及格...
- java归并排序算法
- 手Q体验不满意的地方之(3)——个人设置栏
- [百家争鸣]LYT演讲:人文素养的必要
- springboot项目在测试文件夹报空指针异常