博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Flutter官方文档动画示例小结
阅读量:5874 次
发布时间:2019-06-19

本文共 9875 字,大约阅读时间需要 32 分钟。

目录

  • 基础动画概念和动画类
  • 原始无动画部件
  • 动画示例1(从小变大过渡)
  • 动画示例2(使用 AnimatedWidget )
  • 动画示例3(无限循环动画)
  • 动画示例4(分离部件与动画)
  • 动画示例5(非线性动画)

基础动画概念和动画类

  • Animation Flutter动画库的核心类,任何动画都基于Animation
  • Animation对象可以知道当前动画的状态(value值),不过屏幕上显示的效果是一概不知的,即Animation对象只负责动画过程中的数值变化
  • AnimationController管理动画,例如播放、反转,停用等
  • CurvedAnimation用于实现非线性动画,如快进慢出,慢进快出
  • Tween区间过渡插值,如数字从0到255,动画从黄到绿,分别可以用IntTweenColorTween

原始无动画部件

下面是一个没有动画,宽高固定为300的部件(Widget)

import 'package:flutter/material.dart';void main() => runApp(LogoApp());class LogoApp extends StatefulWidget {  _LogoAppState createState() => _LogoAppState();}class _LogoAppState extends State
with SingleTickerProviderStateMixin { @override Widget build(BuildContext context) { return Center( child: Container( margin: EdgeInsets.symmetric(vertical: 10), // 宽高固定 height: 300, width: 300, child: FlutterLogo(), ), ); }}复制代码

动画示例1(从小变大过渡)

实现图片从小到大(从宽高为0到宽高为300),步骤如下:

  1. 引入动画库import 'package:flutter/animation.dart';,并混入SingleTickerProviderStateMixin
  2. 创建动画控制类,此处可以定义动画的时长
  3. 利用Tween创建动画类,令值在0~300之间变化
  4. 利用addListener方法调用setState更新value
import 'package:flutter/material.dart';import 'package:flutter/animation.dart';void main() => runApp(LogoApp());class LogoApp extends StatefulWidget {  _LogoAppState createState() => _LogoAppState();}class _LogoAppState extends State
with SingleTickerProviderStateMixin { // 定义动画变量 Animation
animation; AnimationController controller; @override void initState() { super.initState(); // 实例化控制类,时长3秒, vsync可以在当前动画对用户不可见时节省机器资源(不进行动画计算) controller = AnimationController(duration: const Duration(seconds: 2), vsync: this); // 在0~300之间变动 animation = Tween
(begin: 0, end: 300).animate(controller) ..addListener(() { // 通过setState令动画中的value产生变化 setState(() {}); }); // 开始播放动画 controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( margin: EdgeInsets.symmetric(vertical: 10), // setState时value的变化产生在这里 height: animation.value, width: animation.value, child: FlutterLogo(), ), ); } @override void dispose() { // 注销动画实例,释放内存 controller.dispose(); super.dispose(); }}复制代码

动画示例2(使用 AnimatedWidget )

使用AnimatedWidget组件简化示例1的代码,不再需要手动调用setState,步骤如下:

  1. 使用AnimatedWidget创建动画部件
  2. 在构造参数中接收Animation参数,并传递给父构造函数的listenable参数
  3. build中通过listenable获得动画中的value
import 'package:flutter/material.dart';import 'package:flutter/animation.dart';void main() => runApp(LogoApp());class LogoApp extends StatefulWidget {  _LogoAppState createState() => _LogoAppState();}class _LogoAppState extends State
with SingleTickerProviderStateMixin { Animation
animation; AnimationController controller; @override void initState() { super.initState(); controller = AnimationController(duration: const Duration(seconds: 2), vsync: this); // 不再需要手动setState animation = Tween
(begin: 0, end: 300).animate(controller); controller.forward(); } @override Widget build(BuildContext context) => AnimatedLogo( animation: animation, ); @override void dispose() { controller.dispose(); super.dispose(); }}class AnimatedLogo extends AnimatedWidget { // 构造参数中的第二个参数为Animation,传递给父构造函数的listenable AnimatedLogo({Key key, Animation
animation}) : super(key: key, listenable: animation); Widget build(BuildContext context) { // 通过listenable获取value final Animation
animation = listenable; return Center( child: Container( margin: EdgeInsets.symmetric(vertical: 10), height: animation.value, width: animation.value, child: FlutterLogo(), ), ); }}复制代码

动画示例3(无限循环动画)

监控动画状态进度,并在过程中根据状态改变动画,实现动画的无限循环,步骤如下:

  1. 增加状态监听addStatusListener
  2. 在监听到动画状态为completed(播放完毕)时,调用reverse()方法反转动画,使动画回到初始状态
  3. 动画回到初始状态后停止时,状态为dismissed,此时再调用forward()方法继续播放,实现无限循环
import 'package:flutter/material.dart';import 'package:flutter/animation.dart';void main() => runApp(LogoApp());class LogoApp extends StatefulWidget {  _LogoAppState createState() => _LogoAppState();}class _LogoAppState extends State
with SingleTickerProviderStateMixin { Animation
animation; AnimationController controller; @override void initState() { super.initState(); controller = AnimationController(duration: const Duration(seconds: 2), vsync: this); /*** * 通过addStatusListener获得当前动画进度,实现无限循环的动画 * * AnimationStatus的四个状态 * 1. AnimationStatus.forward 动画播放 * 2. AnimationStatus.completed 动画播放完成 * 3. AnimationStatus.dismissed 动画回到初始状态后停止 * 4. AnimationStatus.reverse 动画反转 */ animation = Tween
(begin: 0, end: 300).animate(controller) ..addStatusListener((status) { if (status == AnimationStatus.completed) { // 动画完成后反转 controller.reverse(); } else if (status == AnimationStatus.dismissed) { // 反转回初始状态时继续播放,实现无限循环 controller.forward(); } }); // 播放动画 controller.forward(); } @override Widget build(BuildContext context) => AnimatedLogo( animation: animation, ); @override void dispose() { controller.dispose(); super.dispose(); }}class AnimatedLogo extends AnimatedWidget { // 构造参数中的第二个参数为Animation,传递给父构造函数的listenable AnimatedLogo({Key key, Animation
animation}) : super(key: key, listenable: animation); Widget build(BuildContext context) { // 通过listenable获取value final Animation
animation = listenable; return Center( child: Container( margin: EdgeInsets.symmetric(vertical: 10), height: animation.value, width: animation.value, child: FlutterLogo(), ), ); }}复制代码

动画示例4(分离部件与动画)

在前面的动画中可以看到,部件显示的内容和动画混合在一起了,Flutter官网给出了一个可以使动画和部件内容分离的写法 按我理解,所有只是改变宽高(仅当前示例)的内容部件都可以使用这个GrowTransition动画过渡部件 步骤如下:

  1. 将部件内容创建为一个单独的内容部件
  2. 将过渡动画也创建为一个单独的部件,并使用AnimatedBuilder编写过渡的部分
  3. 将动画部件和内容部件组合在一起
import 'package:flutter/material.dart';import 'package:flutter/animation.dart';void main() => runApp(LogoApp());class LogoApp extends StatefulWidget {  _LogoAppState createState() => _LogoAppState();}class _LogoAppState extends State
with SingleTickerProviderStateMixin { Animation
animation; AnimationController controller; @override void initState() { super.initState(); // 创建动画 controller = AnimationController(duration: const Duration(seconds: 2), vsync: this); animation = Tween
(begin: 0, end: 300).animate(controller); controller.forward(); } // 将内容部件和动画组合起来 @override Widget build(BuildContext context) => GrowTransition( animation: animation, child: LogoWidget(), ); @override void dispose() { controller.dispose(); super.dispose(); }}// 内容部件class LogoWidget extends StatelessWidget { Widget build(BuildContext context) => Container( margin: EdgeInsets.symmetric(vertical: 10), child: FlutterLogo(), );}// 动画过渡部件class GrowTransition extends StatelessWidget { GrowTransition({this.child, this.animation}); // 需要有动画过渡效果的部件 final Widget child; // 为部件使用的动画 final Animation
animation; Widget build(BuildContext context) => Center( /** * AnimatedBuilder将宽高定义为过渡状态 * 按我理解,所有只是改变宽高的内容部件都可以使用这个GrowTransition动画过渡部件 * 当然也可以定义一个只改变透明度的动画过渡部件复用 */ child: AnimatedBuilder( animation: animation, builder: (context, child) => Container( height: animation.value, width: animation.value, child: child, ), child: child), );}复制代码

动画示例5(非线性动画)

非线性动画很好理解,就慢进快出,快进慢出等。使用CurvedAnimation类,步骤如下:

  1. 创建AnimationController,定义相关参数
  2. 创建CurvedAnimation,是得其parent参数为前一步创建的动画控制器,参数curve为动画效果
  3. 创建Tween过渡值,调用evaluate()方法,参数即为上一步创建的CurvedAnimation对象
  4. 接着就调用forward()播放动画即可
import 'package:flutter/material.dart';import 'package:flutter/animation.dart';void main() => runApp(LogoApp());class LogoApp extends StatefulWidget {  _LogoAppState createState() => _LogoAppState();}class _LogoAppState extends State
with SingleTickerProviderStateMixin { Animation
animation; AnimationController controller; @override void initState() { super.initState(); controller = AnimationController(duration: const Duration(seconds: 2), vsync: this); // 曲线动画的核心的代码 animation = CurvedAnimation(parent: controller, curve: Curves.easeOut); controller.forward(); } @override Widget build(BuildContext context) => AnimatedLogo( animation: animation, ); @override void dispose() { controller.dispose(); super.dispose(); }}class AnimatedLogo extends AnimatedWidget { // 曲线动画使用的过渡效果 static final _sizeTween = Tween
(begin: 0, end: 300); // 构造参数中的第二个参数为Animation,传递给父构造函数的listenable AnimatedLogo({Key key, Animation
animation}) : super(key: key, listenable: animation); Widget build(BuildContext context) { // 通过listenable获取value final Animation
animation = listenable; return Center( child: Container( margin: EdgeInsets.symmetric(vertical: 10), // 曲线动画部分开始 height: _sizeTween.evaluate(animation), width: _sizeTween.evaluate(animation), // 曲线动画部分结束 child: FlutterLogo(), ), ); }}复制代码

补充,另一个简单示例(修改动画示例1即可)

/**     *  非曲线动画的的另一个示例     *  把animate的参数从controller改成animate即可     */    final Animation curve = CurvedAnimation(parent: controller, curve: Curves.easeOut);    animation = Tween
(begin: 0, end: 300).animate(curve); controller.forward();复制代码

参考

转载于:https://juejin.im/post/5cfcfcecf265da1bba58f749

你可能感兴趣的文章
JS Cookie
查看>>
ubuntu Unable to locate package sysv-rc-conf
查看>>
笔记:认识.NET平台
查看>>
cocos2d中CCAnimation的使用(cocos2d 1.0以上版本)
查看>>
【吉光片羽】短信验证
查看>>
MacBook如何用Parallels Desktop安装windows7/8
查看>>
gitlab 完整部署实例
查看>>
GNS关于IPS&ASA&PIX&Junos的配置
查看>>
七天学会ASP.NET MVC (四)——用户授权认证问题
查看>>
upgrade to iOS7,how to remove stroyboard?
查看>>
影响企业信息化成败的几点因素
查看>>
SCCM 2016 配置管理系列(Part8)
查看>>
zabbix监控部署
查看>>
struts中的xwork源码下载地址
查看>>
Android硬件抽象层(HAL)深入剖析(二)
查看>>
CDays–4 习题一至四及相关内容解析。
查看>>
L3.十一.匿名函数和map方法
查看>>
java面向对象高级分层实例_实体类
查看>>
android aapt 用法 -- ApkReader
查看>>
[翻译]用 Puppet 搭建易管理的服务器基础架构(3)
查看>>