Flutter动画: Animation动画基础(三)

我的博客

本章再练习几个隐式和显式动画, 并且集合二个或多个Animation对象完成交织动画。

首先来看AnimatedContainer

AnimatedContainer

基本上看过Flutter官方动画教程的, 都看过关于AnimatedContainer的示例, 我们也来做一个。 AnimatedContainer是一个隐式动画对象, 无需设置AnimationController来手动控制动画的启动与停止, 只需要设计数值的起始和终值。

AnimatedContainer, 从名字看, 是将常用的Container组件进行了动画处理, 实际也确实如此。 原来Container的大部分参数都可以设置动画数值。 同时还增加了一个非常好的控制方法onEnd:(){}, 方便在收到动画结束信息后, 可以切换其它操作。

import 'package:flutter/material.dart';

class MyAnimatedContainerDemo extends StatefulWidget {
  @override
  _MyAnimatedContainerDemoState createState() =>
      _MyAnimatedContainerDemoState();
}

class _MyAnimatedContainerDemoState extends State<MyAnimatedContainerDemo>
    with SingleTickerProviderStateMixin {
  bool isActive = false;
  final Duration duration = Duration(milliseconds: 2000);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('点击缩放-AnimatedContainer组件')),
      body: Center(
        child: AnimatedContainer(
          duration: duration,
          width: isActive ? 200 : 100,
          height: isActive ? 200 : 100,
          decoration: BoxDecoration(
              color: isActive ? Colors.red : Colors.blue,
              borderRadius: BorderRadius.circular(isActive ? 20 : 0)),
          onEnd: () {
            setState(() {
              isActive = !isActive;
            });
          },
          child: InkWell(
            onTap: () {
              setState(() {
                isActive = !isActive;
              });
            },
            child: CircleAvatar(
              backgroundImage: AssetImage('assets/images/head.jpg'),
            ),
          ),
        ),
      ),
    );
  }
}

效果如下:

AnimatedContainer

从代码中可以看到, 我们对AnimatedContainer的width, height, color和borderRadius都进行了设置, 并且在动画结束(onEnd)的时候, 对数值进行了反转, 因此带动动画也Reverse了。

RotationTransition

RotationTransition是一个旋转组件, 其child默认围绕中心旋转。 RotationTransition的参数turns是一个Animation<double>对象, 用于更新当前旋转的角度。看示例。

import 'package:flutter/material.dart';

class MyRotationTransitionDemo extends StatefulWidget {
  @override
  _MyRotationTransitionDemoState createState() =>
      _MyRotationTransitionDemoState();
}

class _MyRotationTransitionDemoState extends State<MyRotationTransitionDemo>
    with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<double> turns;
  Duration duration = Duration(milliseconds: 3000);
  @override
  void initState() {
    super.initState();
    controller = AnimationController(vsync: this, duration: duration);
    turns = Tween<double>(begin: 0.0, end: 1.0).animate(controller);
    controller.repeat();
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('RotationTransition组件')),
      body: Center(
        child: RotationTransition(
          turns: turns,
          child: Container(
            width: 200,
            height: 200,
            padding: EdgeInsets.all(5.0),
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              border: Border.all(color: Colors.blue),
            ),
            child: CircleAvatar(
              backgroundImage: AssetImage('assets/images/head.jpg'),
            ),
          ),
        ),
      ),
    );
  }
}

效果如下:

RotationTransition

复杂交织(组合)动画

现在我们来做一个比较复杂的交织(组合)动画。 先放效果图。

complex_animation

从图中可以看到,

  • 外部圈内的颜色周期性变化
  • 头像周期性的缩小、放大
  • 头像周期性的旋转

其实这是一个比较简单的交织(组合)动画, 只是简单的将AnimatedContainer、ScaleTransition和RotationTransition进行了组合而已, 三者没有关联, 各自负责自己的动画。

来看代码。

import 'dart:async';

import 'package:flutter/material.dart';

class MyComplexAnimationDemo extends StatefulWidget {
  @override
  _MyComplexAnimationDemoState createState() => _MyComplexAnimationDemoState();
}

class _MyComplexAnimationDemoState extends State<MyComplexAnimationDemo>
    with TickerProviderStateMixin {
  // 控制AnimatedContainer的动画
  Timer timer;
  bool isActive = true;

  // 控制widget缩放scale
  AnimationController scaleController;
  Animation<double> scale;

  // 控制widget旋转rotation
  AnimationController rotationController;
  Animation<double> turns;

  Duration duration = Duration(milliseconds: 1000);

  @override
  void initState() {
    super.initState();
    // 定时让AnimatedContainer的参数做变动
    timer = Timer.periodic(duration, (t) {
      setState(() {
        isActive = !isActive;
      });
    });

    // 设置缩放控制器和数值区间
    scaleController = AnimationController(vsync: this, duration: duration);
    scale = Tween<double>(begin: 0.8, end: 1.0).animate(scaleController);
    scaleController.repeat(reverse: true);

    // 设置旋转控制器和数值区间, 旋转速度慢一点(持续时间长一点), 不做状态监听, 让动画一直重复就好
    rotationController =
        AnimationController(vsync: this, duration: duration * 8);
    turns = Tween<double>(begin: 1.0, end: 0.0).animate(rotationController);
    rotationController.repeat();
  }

  @override
  void dispose() {
    timer?.cancel();
    timer = null;
    scaleController?.dispose();
    rotationController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('复杂交织动画')),
      body: Center(
        child: AnimatedContainer(
          width: 200,
          height: 200,
          padding: EdgeInsets.all(10),
          duration: duration,
          decoration: BoxDecoration(
            color: isActive ? Colors.blue : Colors.grey,
            shape: BoxShape.circle,
          ),
          child: ScaleTransition(
            scale: scale,
            child: RotationTransition(
              turns: turns,
              child: CircleAvatar(
                backgroundImage: AssetImage('assets/images/head.jpg'),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

好吧, 文章已经够长了, 后面抽空再写一篇带顺序关系的动画。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270