Flutter开发进阶之动画

Flutter开发进阶之动画

在Flutter中,动画是至关重要的一个部分,它能够为应用程序提供更加丰富和生动的用户体验,Flutter中的动画系统是UI框架的核心功能之一,也是开发者学习Flutter框架的重要部分,由于动画原理在所有程序中都是相同的,即视觉暂留,因此理解这一原理对于更好地使用Flutter的动画系统至关重要;
动画在应用程序中具有许多用途,例如引导用户注意力、增强视觉效果、提供更好的交互体验等,通过精心设计的动画,应用程序可以变得更加有趣、吸引人,并提高用户的参与度和满意度;
Flutter开发进阶之动画
Flutter开发中动画可以有多种分类,其中可以通过是否模拟现实世界中物理行为物理动画和补间动画。

物理动画

物理动画模拟现实世界中的物理行为,如重力、弹性、摩擦力等;
Flutter的AnimatedPhysics组件提供了这种能力,可以为AnimatedPhysics组件提供一个AccelerationSpec和DecelerationSpec,以定义动画的加速和减速行为。

  
  Widget build(BuildContext context) {  
    return AnimatedPhysics(  
      mass: 100.0,  
      acceleration: 9.8, // 重力加速度  
      deceleration: 0.5, // 阻尼系数,决定物体下落后的减速程度  
      child: Container(  
        width: 200.0,  
        height: 200.0,  
        color: Colors.red,  
      ),  
      animationId: _animationId, // 动画ID,用于标识这个动画,用于后续的动画控制操作,例如暂停、恢复等。  
    );  
  }  

补间动画

补间动画是更传统的动画方式,它允许你定义动画的开始和结束状态,以及中间过渡状态;
Flutter的AnimatedBuilder和AnimatedCrossFade组件提供了这种能力,还可以通过Tween来构建。

  
  Widget build(BuildContext context) {  
    return AnimatedBuilder(  
      animation: _animationController,  
      builder: (context, child) {  
        if (_isFirst) {  
          return Container(color: Colors.red, child: child);  
        } else {  
          return Container(color: Colors.green, child: child);  
        }  
      },  
      child: AnimatedCrossFade(  
        duration: Duration(seconds: 1),  
        firstChild: Container(color: Colors.red), // 第一个显示的子组件,初始为红色容器  
        secondChild: Container(color: Colors.green), // 第二个显示的子组件,初始为绿色容器  
        crossfadeState: _isFirst ? 1 : 0, // 控制动画状态,true表示第二个子组件显示,false表示第一个子组件显示  
        firstChildBuilder: (BuildContext context, child, bool visible) { // 可选,用于定制第一个子组件的动画效果,这里我们保持默认行为,不进行定制。  
          return visible ? child : null;  
        },  
        secondChildBuilder: (BuildContext context, child, bool visible) { // 可选,用于定制第二个子组件的动画效果,这里我们保持默认行为,不进行定制。  
          return visible ? child : null;  
        },  
      ),  
      animationId: _animationController.id, // 动画ID,用于标识这个动画,用于后续的动画控制操作,例如暂停、恢复等。这里我们使用了和之前示例中一样的ID。  
    );  
  }  

还可以根据动画的触发方式(隐式和显式)分为隐式动画和显式动画。

隐式动画

隐式动画是Flutter框架自动处理的动画,通常可以使用对应的组件(AnimatedOpacity、AnimatedContainer、AnimatedPadding、AnimatedPositioned、AnimatedSwitcher等)来实现,通过简单的属性设置来实现动画效果,而不需要手动创建和管理动画控制器。

  
Widget build(BuildContext context) {  
  return Column(  
    mainAxisAlignment: MainAxisAlignment.center,  
    children: [  
      // 示例1:使用AnimatedOpacity创建动画  
      AnimatedOpacity(  
        value: _animationValue, // 动画值范围:0.0(完全透明)到1.0(完全不透明)  
        duration: _controller.duration, // 使用AnimationController的持续时间,确保动画同步。  
        child: Container(  
          width: 100,  
          height: 100,  
          color: Colors.red,  
        ),  
      ),  
      // 示例2:使用AnimatedContainer创建动画  
      AnimatedContainer(  
        duration: _controller.duration, // 使用AnimationController的持续时间,确保动画同步。  
        curve: Curves.bounceInOut, // 动画曲线  
        child: Container(  
          width: 100,  
          height: 50,  
          color: Colors.green,  
        ),  
      ),  
      // 其他使用动画效果的子项...  
    ],  
  );  
}

显式动画

显式动画是开发者需要手动创建和管理的动画,在Flutter中,这通常通过使用Animated组件(例如AnimatedPositioned,AnimatedBuilder等)以及AnimationController类来完成;
需要明确指定动画的起始状态、结束状态以及过渡的时间和曲线。

class MyAnimatedWidget extends StatefulWidget {  
    
  _MyAnimatedWidgetState createState() => _MyAnimatedWidgetState();  
}  
  
class _MyAnimatedWidgetState extends State<MyAnimatedWidget> with SingleTickerProviderStateMixin {  
  AnimationController _controller;  
  Tween<double> _tween = Tween<double>(  
    begin: 0.0,  
    end: 200.0,  
  ).animate(_controller);  
  
    
  void initState() {  
    super.initState();  
    _controller = AnimationController(  
      vsync: this,  
      duration: Duration(seconds: 2), // 动画持续时间  
    );  
  }  
  
    
  Widget build(BuildContext context) {  
    return Column(  
      mainAxisAlignment: MainAxisAlignment.center,  
      children: [  
        AnimatedPositioned(  
          animation: _controller, // 将动画控制器绑定到AnimatedPositioned上  
          duration: _controller.duration, // 使用AnimationController的持续时间,确保动画同步。  
          x: 0, // x位置保持不变,仅y位置进行动画处理。  
          y: _tween.value, // 使用Tween的值作为y位置。随着动画的进行,y位置会从0变化到200。  
          child: Container(  
            width: 100,  
            height: 100,  
            color: Colors.red,  
          ),  
        ),  
      ],  
    );  
  }  
}

这些动画都是一些动画元素,可以将多个动画元素组装成复杂动画(Complex Animations),通常指交错动画、序列动画、交错动画、组合动画等;
除了使用系统提供的组件去构建动画外,我们还可以使用CustomPainter构建自定义路径动画。

自定义路径动画

自定义路径动画可以根据需要绘制任何形状的路径,并在动画中改变路径的形状、位置和颜色等属性实现相应的效果。

class MyPainter extends CustomPainter {  
    
  bool shouldRepaint(CustomPainter oldDelegate) {  
    // 返回true表示需要重新绘制,这里我们简单地将返回true,以便每次重新渲染时都会重新绘制路径。  
    return true;  
  }  
  
    
  void paint(Canvas canvas, Size size) {  
    // 获取屏幕的宽高,以便根据需要调整绘制的比例。  
    var paint = Paint()..strokeCap = StrokeCap.round;  
    paint.strokeWidth = 10.0;  
    paint.color = Colors.red; // 设置画笔颜色为红色。  
  
    // 创建路径并绘制。这里我们只是简单地将一个圆形的路径绘制在屏幕上。您可以根据需要创建复杂的路径。  
    var path = Path()..moveTo(0, 0)..circle(size.width / 2, size.height / 2, size.width / 4); // 在屏幕中心绘制一个圆形的路径。您可以根据需要修改路径的形状和位置。  
    canvas.drawPath(path, paint);  
  }  
}

除此之外,还可以通过使用Flutter对应的动画库来创建动画。

spring_simulation

spring_simulation是一种物理模拟器,用于创建具有弹簧效果的动画;
它基于弹簧动力学原理,通过模拟弹簧的伸展、压缩和反弹等行为,实现动画的逼真效果。

class MyApp extends StatelessWidget {  
    
  Widget build(BuildContext context) {  
    return MaterialApp(  
      title: 'SpringSimulation Example',  
      theme: ThemeData(primarySwatch: Colors.blue),  
      home: Scaffold(  
        appBar: AppBar(title: Text('SpringSimulation Example')),  
        body: Center(  
          child: SpringSimulation(  
            // 定义弹簧模拟器的参数  
            mass: 1.0, // 质量(kg)  
            stiffness: 400.0, // 刚度(N/m)  
            damping: 5.0, // 阻尼(N·s/m)  
            target: 0.0, // 目标位置(m)  
            // 定义弹簧的初始位置和速度  
            initialPosition: -1.0, // 初始位置(m)  
            initialVelocity: 2.0, // 初始速度(m/s)  
            // 定义弹簧的约束条件(可选)  
            constraints: SpringConstraints(min: -1.0, max: 1.0), // 限制弹簧的最小和最大位置范围  
            // 将弹簧附加到屏幕上,这里使用了一个简单的圆点作为示例  
            onUpdate: (mass, stiffness, damping, position, velocity) {  
              Positioned(  
                  left: position * 300, // 将弹簧的位置转换为屏幕坐标  
                  child: Container(  
                    width: 30,  
                    height: 30,  
                    decoration: BoxDecoration(shape: BoxShape.circle), // 创建一个圆点作为弹簧的表示  
                    child: Icon(Icons.play_arrow), // 使用播放箭头图标作为示例,您可以根据需要自定义图标或文本等UI元素。  
                  ),  
              );  
            },  
          ),  
        ),  
      ),  
    );  
  }  
}

还有很多,就不一一列举了。
在Flutter开发中构建动画,需要注意的点是:
选择合适的动画库
根据项目需求选择合适的动画库,如Tween、Dart-Animation-Lib、flutter_animator等。
理解动画生命周期
Flutter中的动画有一个开始、执行和结束的过程。你需要确保在动画开始时设置动画的初始状态,并在动画结束时设置动画的结束状态。
使用状态管理
Flutter中的动画通常与状态变化相关联,因此,建议使用Flutter的状态管理解决方案,如Redux或Bloc,来管理动画状态。
优化性能
在构建动画时,需要注意性能问题,避免在动画执行期间进行不必要的渲染或计算操作,这可能导致动画卡顿。
测试不同设备和场景
在不同设备和不同场景下测试动画效果,以确保动画在不同环境下都能正常工作。
考虑用户反馈
根据用户反馈调整动画效果,以提供更好的用户体验。
遵循Material Design规范
如果项目需要遵循Material Design规范,确保动画效果与规范保持一致。

如何对动画优化性能

对于Flutter开发中的性能优化,有以下几个方向。
避免不必要的渲染和计算
在动画执行期间,应避免进行不必要的渲染或计算操作,这可以减少GPU和CPU的工作负担,提高动画性能;
比如使用Reusable或MemoizedListTile等复用组件,这些组件可以在列表中使用,避免在列表滚动时重复创建和销毁组件,从而提高性能;
使用const关键字,在可能的情况下,尽量使用const关键字来创建不可变对象,这样可以避免在动画执行期间进行不必要的重新构建;
避免在动画执行期间进行复杂的布局和计算,在动画执行期间,应避免进行复杂的布局和计算操作,这些操作可能会导致不必要的渲染和计算;
使用ListView的physics属性,通过设置physics属性为NeverScrollableScrollPhysics(),可以避免在滚动时触发不必要的布局和渲染;
使用WidgetsBinding.instance.addPostFrameCallback,这个方法可以用来在每一帧渲染后执行回调函数,可以在这里进行一些必要的计算和更新操作,避免在动画执行期间进行不必要的渲染和计算;
使用Binding.instance.addPostFrameCallback,这个方法与WidgetsBinding.instance.addPostFrameCallback类似,但作用范围更广,可以在整个应用中避免不必要的渲染和计算。
使用列表复用
在处理大量数据时,使用列表复用技术可以避免频繁创建和销毁列表项,从而提高性能;
比如通过使用ListTile的key属性,可以确保列表项的唯一性,从而实现列表复用;
另外,也可以使用Reusable组件或MemoizedListTile组件来实现列表复用。
使用GPU加速
Flutter的渲染引擎支持GPU加速,通过将部分或全部渲染工作交给GPU处理,可以提高动画性能。
优化Widget树
在构建动画时,应尽量减少Widget树的深度和复杂度,避免不必要的布局和重绘操作,从而提高性能。
使用帧调度器
通过使用Flutter的帧调度器,可以更好地控制动画的执行时间和帧率,从而提高性能。
使用Profile工具
Flutter提供了Profile工具,可以用来分析应用的性能瓶颈,通过使用Profile工具,可以找到性能问题并进行针对性的优化。
使用高性能的动画库
如Tween等高性能的动画库,可以提供更好的动画性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/319138.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实时时钟芯片DS1302单片机C语言驱动程序

实时时钟RTC相关索引 1.单片机RTC及时钟芯片的时间到底从哪一年起始&#xff1f; 2.STM32F103单片机内部RTC实时时钟驱动程序 3.实时时钟芯片DS1302单片机C语言驱动程序 一、DS1302简介 DS1302 是 DALLAS&#xff08;达拉斯&#xff09;公司推出的一款涓流充电时钟芯片。 主…

Aigtek超声功率放大器的选型技巧及参数指标有哪些

超声功率放大器是一种广泛应用于声学测量、医疗成像、声纳等领域的装置&#xff0c;其作用是将输入信号的功率放大到需要的水平。在选型超声功率放大器时&#xff0c;需要考虑一些关键的技巧和参数指标&#xff0c;以确保选择合适的设备来满足特定的需求。 首先&#xff0c;需要…

【java八股文】之Spring系列篇

1、你怎么理解Spring&#xff1f; Spring是个轻量级的框架&#xff0c;简化了应用的开发程序&#xff0c;提高开发人员的系统维护性&#xff0c;不过配置消息比较繁琐&#xff0c;所以后面才出选了SpringBoot的框架。 Spring的核心组件 &#xff1a; Spring Core 、 Spring Con…

【Python数据可视化】matplotlib之设置子图:绘制子图、子图共享x轴坐标

文章传送门 Python 数据可视化matplotlib之绘制常用图形&#xff1a;折线图、柱状图&#xff08;条形图&#xff09;、饼图和直方图matplotlib之设置坐标&#xff1a;添加坐标轴名字、设置坐标范围、设置主次刻度、坐标轴文字旋转并标出坐标值matplotlib之增加图形内容&#x…

CDSP和CISP证书,选择哪个?

&#x1f3af;CDSP和CISP是两种与信息安全领域相关的专业认证。它们有一些相似之处&#xff0c;但也存在一些显著的区别。本文将详细介绍CDSP认证和CISP认证的相同点和区别。 &#x1f451;CDSP和CISP的相同点&#xff1a; 1.行业认可&#xff1a;CDSP和CISP都是行业广泛认可的…

机器视觉系统选型-参数—景深

镜头在垂直方向上&#xff0c;能清晰成像的空间距离(清晰成像范围)&#xff0c;称为景深

强化学习应用(八):基于Q-learning算法的无人车配送路径规划(通过Python代码)

一、Q-learning算法介绍 Q-learning是一种强化学习算法&#xff0c;用于解决基于环境的决策问题。它通过学习一个Q-table来指导智能体在不同状态下采取最优动作。下面是Q-learning算法的基本步骤&#xff1a; 1. 定义环境&#xff1a;确定问题的状态和动作空间&#xff0c;并…

MyBatis第二课,灰度发布,@Results注解,使用xml书写mysql

目录 打印MyBatis的日志配置&#xff1a; 灰度发布:指发布环境&#xff0c;比如发布环境有200台机器&#xff0c;发布的时候是一批一批的机器的发布 2.删除与修改 使用Results注解&#xff0c;这样就和上面的别名一个意思&#xff0c;column是数据库的列 自动转驼峰&#…

H5网站封装成App的高效转换之旅

在移动互联网时代&#xff0c;App&#xff08;应用程序&#xff09;和H5&#xff08;HTML5网站&#xff09;是两种常见的移动解决方案。App通常提供更流畅的用户体验和更丰富的功能&#xff0c;而H5网站则以其开发成本低、更新快捷和无需安装等优势受到青睐。尽管如此&#xff…

Apache-Common-Pool2中对象池的使用方式

最近在工作中&#xff0c;对几个产品的技术落地进行梳理。这个过程中发现一些朋友对如何使用Apache的对象池存在一些误解。所以在写作“业务抽象”专题的空闲时间里&#xff0c;本人觉得有必要做一个关于对象池的知识点和坑点讲解。Apache Common-Pool2 组件最重要的功能&#…

【快速解决】保姆级Anaconda安装教程

目录 第一步 ​编辑第二步 ​编辑第三步 第四步 第五步 第六步 ​编辑 第七步 第八步 第九步 第一步 在anaconda清华大学开源软件镜像站下载anaconda。点击这里进入 我这里选的是windows-x86_64。 第二步 下载好以后进行安装 第三步 第四步 第五步 选择…

【操作系统】在阅读论文:OrcFS: Orchestrated file system for flash storage时需要补充的基础知

在阅读论文&#xff1a;OrcFS: Orchestrated file system for flash storage是需要补充的基础知识 这篇论文是为了解决软件层次之间的信息冗余问题 To minimize the disk traffic, the file system buffers the updates and then flushes them to the disk as a single unit, …

通达信波动指数指标公式,识别盘整还是趋势

波动指数(Choppiness Index)是由澳大利亚商品交易员E.W. Dreiss开发的技术指标&#xff0c;用来判断市场是盘整还是趋势。该指标属于非方向性指标&#xff0c;不用于判断市场方向&#xff0c;而仅用于识别市场趋势。 指标的取值范围为0到100&#xff0c;数值越高&#xff0c;表…

[足式机器人]Part2 Dr. CAN学习笔记-Advanced控制理论 Ch04-12+13 不变性原理+非线性系统稳定设计

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-Advanced控制理论 Ch04-1213 不变性原理非线性系统稳定设计 1. Invariance Princilpe-LaSalle;s Theorem不变性原理2. Nonlinear Basic Feedback Stabilization 非线性系统稳定设计 1. Invarianc…

Visual Studio Code1.67版本已正式发布,新增Rust指南

Visual Studio Code1.67版本已正式发布&#xff0c;该版本包含大量增强生产力的更新项&#xff1a; 资源管理器文件嵌套 通过这次更新&#xff0c;用于浏览和管理文件和文件夹的Visual Studio Code的资源管理器工具现在支持基于名称嵌套相关文件。 资源管理器现在支持根据文…

python学习笔记10(选择结构2、循环结构1)

&#xff08;一&#xff09;选择结构2 1、if……else……语句 #&#xff08;1&#xff09;基本格式 numbereval(input("请输入您的6位中奖号码&#xff1a;")) if number123456:print("恭喜您&#xff0c;中奖了") else:print("未中奖")#&…

JVM内存结构 vs. Java对象模型 vs. Java内存模型

文章目录 0.三者的区别1.JVM内存结构2.Java对象模型3.Java内存模型&#xff08;JMM&#xff09;3.1 为什么需要JMM3.2 JMM是规范3.3 JMM是工具类和关键字的原理3.4 最重要的三点内容 0.三者的区别 JVM内存结构&#xff1a;和Java虚拟机的运行时区域有关。 Java对象模型&#…

负荷预测 | Python基于CEEMDAN-VMD-BiGRU的短期电力负荷时间序列预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 提出一种分解去噪、重构分解的 CEEMDAN-VMD-BiGRU组合预测方法&#xff1a; 1 采用CEEMDAN将原始电力负荷数据分解成一组比较稳定的子序列&#xff0c;联合 小波阈值法将含有噪声的高频分量去噪&#xff0c;保留含有信…

竞赛练一练 第29期:GESP和电子学会相关题目练习

CIE一级2021.09_无奈的Jaime 小宝在房间吵闹&#xff0c;妈妈让Jaime想办法安抚小宝。Jaime在房间来回走动思考方法。最后也没想出方法只能摊开双手说 “sorry&#xff01;”。 1. 准备工作 &#xff08;1&#xff09;添加背景&#xff1a;Bedroom 3&#xff1b; &#xff0…

[解决方案]运行时错误‘53’,文件未找到:MathPage.WLL

问题描述 mathtype使用报错,运行时错误‘53’,文件未找到:MathPage.WLL 解决方案 一、首先确定自己电脑的位数(这里默认大家的电脑都是64位) 二、右击MathType桌面图标,点击“打开文件所在位置”,然后找到MathPage.WLL文件所在位置 MathPage.WLL位置:D:\mathtype\…
最新文章