Flutter入门系列-动画 Animation

1. 普通的动画 Alpha Scale Slide Rotate

普通控件动画创建步骤:

1. AnimationController

2. Animation 通过Tween创建动画

3. 将动画 Animation 设置给 RotateAnimation--> Widget

4. controller.repeat(), forward(), reverse(),

import 'package:flutter/material.dart';


//https://blog.csdn.net/zhakesipailuo/article/details/89882968
class WidgetAnimation extends StatefulWidget {
  @override
  _WidgetAnimationState createState() => _WidgetAnimationState();
}

//注意:在创建AnimationController的时候,需要混入TickerProviderStateMixin
class _WidgetAnimationState extends State<WidgetAnimation>
    with TickerProviderStateMixin {
  AnimationController _controller;
  Animation _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: Duration(seconds: 1));
    _animation = Tween(begin: 0.0, end: 1.0).animate(_controller) // Tween 线性动画 CurvedAnimation 非线性动画
      ..addListener(() {
        setState(() {});
      });
    _controller.forward(); 
    //forward() 开始动画
    //repeat()  重复动画
    //reverse() 反向执行动画
    //AnimatedBuilder 也可以创建动画Widget 这样的效果是缩小了build范围 有优化效果
    //AnimatedWidget 可以创建动画Widget 
  }

  // RotateTransition turns: _animation
  // ScaleTransition scale:  _animation
  // FadeTransition opacity: _animation,
  // SlideTransition position: _animation
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Widget动画'),
      ),
      body: Container(
        alignment: Alignment.center,
        child: Container(
          child: FadeTransition(
            opacity: _animation,
            child: Container(
              width:  200,
              height: 200,
              color: Colors.blue,
            ),
          ),
        ),
      ),
    );
  }
}

2. 使用 AnimatedBuilder 来创建动画

import 'package:flutter/material.dart';

//AnimatedBuilder来创建具有动画效果的Widget
class AnimatedBuilderPage extends StatefulWidget {
  @override
  _AnimatedBuilderPageState createState() => _AnimatedBuilderPageState();
}

class _AnimatedBuilderPageState extends State<AnimatedBuilderPage>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: const Duration(seconds: 3));
    //_animation = Tween<double>(begin: 0.0, end: 300.0).animate(_controller);
    //CurvedAnimation需要配合Tween合作才能生效
    //_animation = CurvedAnimation(parent: _controller, curve: Curves.bounceInOut);
    //_animation = Tween<double>(begin: 0.0, end: 300.0).animate(_animation); //CurvedAnimation 是作用与Tween上的,改变变化速率
    _animation = Tween<double>(begin: 0.0, end: 300.0).animate(_controller);
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AnimatedBuilder'),
      ),
      body: Container(
        child: Center(
          child: AnimatedBuilder(
            animation: _animation,
            // 注意:这里需要指定child,否则会看不到效果 这里指定了图片为child
            child: Image.asset('images/lovely_girl.jpg'),
            builder: (BuildContext context, Widget child) {
              return Container(
                width: _animation.value,
                height: _animation.value,
                child: child,
              );
            },
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    //2. 注意:需要这里的_controller.dispose() 调用需要在super.dispose()之前调用
    _controller.dispose();
    super.dispose();
  }
}

3. 继承 AnimatedWidget 实现动画

import 'package:flutter/material.dart';

//创建继承自AnimatedWidget的具有动画效果的Widget
class AnimatedWidgetPage extends StatefulWidget {
  @override
  _AnimatedWidgetPageState createState() => _AnimatedWidgetPageState();
}

class _AnimatedWidgetPageState extends State<AnimatedWidgetPage>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: Duration(seconds: 2));
    _animation = Tween<double>(begin: 0.0, end: 300).animate(_controller);
    _animation.addStatusListener((status) {
      if (status == AnimationStatus.forward) {
        // 动画正在正向执行
        print('forward....');
      } else if (status == AnimationStatus.completed) {
        // 动画在中点结束
        print('completed....');
      } else if (status == AnimationStatus.reverse) {
        // 动画正在反向执行
        print('reverse....');
      } else if (status == AnimationStatus.dismissed) {
        //动画在起点结束
        print('dismissed...');
      }
    });
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AnimatedWidget'),
      ),
      body: Container(
        child: Center(
          child: GrowableWidget(
            animation: _animation,
          ),
        ),
      ),
    );
  }

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

class GrowableWidget extends AnimatedWidget {
  GrowableWidget({Key key, Animation<double> animation})
      : super(key: key, listenable: animation);

  @override
  Widget build(BuildContext context) {
    final Animation<double> animation = listenable;
    return Center(
      child: Image.asset(
        'images/lovely_girl.jpg',
        width: animation.value,
        height: animation.value,
      ),
    );
  }
}

4. Hero 动画 Hero 

import 'package:flutter/material.dart';
import 'package:flutter_widgets/animation/hero_animation_next_page.dart';

class HeroAnimationPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('HeroAnimation'),
      ),
      body: Stack(
        children: [
          Container(
            margin: EdgeInsets.only(top: 400),
            alignment: Alignment.topCenter,
            child: Hero(
                tag: 'avatar',
                child: ClipOval(
                  child: Image.asset(
                    'images/lovely_girl.jpg',
                    fit: BoxFit.cover,
                    width: 100,
                    height: 100,
                  ),
                )),
          ),
          Align(
            alignment: Alignment.topCenter,
            child: Container(
              margin: EdgeInsets.only(left: 10, right: 10),
              child: MaterialButton(
                color: Colors.blue,
                //minWidth: double.infinity,
                onPressed: () {
                  Navigator.of(context).push(PageRouteBuilder(pageBuilder:
                      (BuildContext context, Animation animation,
                          Animation secondaryAnimation) {
                    return new FadeTransition(
                      opacity: animation,
                      child: HeroAnimationNextPage(),
                    );
                  }));
                },
                child: Text('点击跳转到下一个Hero页面', style: TextStyle(color: Colors.white),),
              ),
            ),
          )
        ],
      ),
    );
  }
}
import 'package:flutter/material.dart';

class HeroAnimationNextPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('HeroAnimationNext'),
      ),
      body: Stack(
        children: [
          Container(
            margin: EdgeInsets.only(top: 200),
            alignment: Alignment.topCenter,
            child: Hero(
                tag: 'avatar', // 和上一个Hero页面一样,也需要相同的tag来做标记,同时用Hero来包裹
                child: ClipOval(
                  child: Image.asset(
                    'images/lovely_girl.jpg',
                    fit: BoxFit.cover,
                    width: 100,
                    height: 100,
                  ),
                )),
          ),
          Align(
            alignment: Alignment.topCenter,
            child: Container(
              margin: EdgeInsets.only(left: 10, right: 10),
              child: MaterialButton(
                color: Colors.blue,
                minWidth: double.infinity,
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: Text(
                  '点击跳转到上一个Hero页面',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }
}

5. 路由动画 利用PageRouterBuilder 来构建路由,用FadeTransition来包裹跳转的Page

import 'package:flutter/material.dart';
import 'package:flutter_widgets/animation/route_next_page.dart';

//路由动画
class RouteAnimationPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Route动画'),
      ),
      body: Container(
        child: Column(
        children: [
          Container(
            margin: EdgeInsets.only(left: 10, right: 10),
            child: MaterialButton(
              minWidth: double.infinity,
              color: Colors.blue,
              onPressed: () {
                Navigator.of(context).push(PageRouteBuilder(
                    transitionDuration:Duration(microseconds: 2000), // 动画时间为500ms
                    pageBuilder: (BuildContext context, Animation animation,
                        Animation secondaryAnimation) {
                      return FadeTransition(
                        opacity: animation,
                        child: RouteNextPage(),
                      );
                    }));
              },
              child: Text(
                '跳转到下一个页面',
                style: TextStyle(color: Colors.white),
              ),
            ),
          )
        ],
      )),
    );
  }
}
import 'package:flutter/material.dart';

class RouteNextPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Route动画下一页面'),
      ),
      body: Container(
        child: Column(
          children: [
            Container(
              margin: EdgeInsets.only(left: 10, right: 10),
              child: MaterialButton(
                minWidth: double.infinity,
                color: Colors.blue,
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: Text('退出本页面', style: TextStyle(color: Colors.white),),
              ),
            )
          ],
        ),
      ),
    );
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值