当前位置: 首页 > 工具软件 > yyets_flutter > 使用案例 >

flutter动画

吴浩博
2023-12-01

基础动画

  • Animation:Flutter动画中的核心类,此类是抽象类,通常情况下使用其子类:AnimationController,可以获取当前动画的状态和值,也可以添加其状态变化监听和值变化监听。
  • Curve:决定动画执行的曲线,和Android中的Interpolator(差值器)是一样的,负责控制动画变化的速率,系统已经封装了10多种动画曲线,详见Curves类。差值器
  • AnimationController:动画控制器,控制动画的开始、停止。继承自Animation。
  • Tween:映射生成不同范围的值,AnimationController的动画值是double类型的,如果需要颜色的变化,Tween可以完成此工作。
class AnimationWidgetState extends State<AnimationTestPage>
    with SingleTickerProviderStateMixin {
  late Animation<double> _animation;
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(vsync: this, duration: const Duration(seconds: 1));
    _animation = CurvedAnimation(parent: _controller, curve: Curves.bounceIn);
    _animation = Tween<double>(begin: 0.0, end: 400).animate(_controller)
      ..addListener(() {
        setState(() {});
      });
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) => MaterialApp(
        home: Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Image.network(
                  'https://th.bing.com/th/id/OIP.3hG2qwUAodmXmKQuKe6pqAHaFj?w=240&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',
                  height: _animation.value,
                  width: _animation.value,
                ),
                TextButton(
                    onPressed: () {
                      _animation = Tween<double>(begin: 0.0, end: 400)
                          .animate(_controller)
                        ..addListener(() {
                          setState(() {});
                        });
                      _controller.forward();
                      _controller.reverse();
                    },
                    child: const Text('开始播放')),
                TextButton(
                    onPressed: () {
                      _animation = Tween<double>(begin: 400, end: 0.0)
                          .animate(_controller)
                        ..addListener(() {
                          setState(() {});
                        });
                      _controller.forward();
                      _controller.reverse();
                    },
                    child: const Text('重置播放')),
              ],
            ),
          ),
        ),
      );
}

还可以通过继承AnimatedWidget方式实现

class AnimationWidget extends AnimatedWidget {
  const AnimationWidget({Key? key, required Listenable listenable})
      : super(key: key, listenable: listenable);

  @override
  Widget build(BuildContext context) {
    var anim = listenable as Animation<double>;
    return Image.network(
      'https://th.bing.com/th/id/OIP.3hG2qwUAodmXmKQuKe6pqAHaFj?w=240&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',
      height: anim.value,
      width: anim.value,
    );
  }
}

class AnimatedState extends State<AnimationTestPage>
    with SingleTickerProviderStateMixin {
  late Animation<double> _animation;
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(vsync: this, duration: const Duration(seconds: 1));
    _animation = CurvedAnimation(parent: _controller, curve: Curves.easeIn);
    _animation = Tween<double>(begin: 0.0, end: 400).animate(_controller);
    _animation.addStatusListener((status) {
      print('动画状态 name=${status.name}, index=${status.index}');
    });

    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose(); //页面销毁是回收动画资源
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => MaterialApp(
        home: Scaffold(
          body: Center(
            child: Column(
              children: [
                Column(
                  children: [
                    AnimationWidget(listenable: _animation),
                    TextButton(
                        onPressed: () {
                          _controller.reverse();
                        },
                        child: const Text('播放反转')),
                    TextButton(
                        onPressed: () {
                          _controller.forward();
                        },
                        child: const Text('播放正序')),
                  ],
                )
              ],
            ),
          ),
        ),
      );
}

路由切换动画

路由添加跳转动画PageRouteBuilder

class AnimationPage1 extends StatelessWidget {
  const AnimationPage1({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp(
        home: Scaffold(
          body: Center(
            child: Stack(
              alignment: Alignment.center,
              children: [
                Image.network(
                    'https://th.bing.com/th/id/OIP.3hG2qwUAodmXmKQuKe6pqAHaFj?w=240&h=180&c=7&r=0&o=5&dpr=2&pid=1.7'),
                ElevatedButton(
                  child: const Text('跳转'),
                  onPressed: () {
                    //路由地址跳转
                    // Navigator.of(context).popAndPushNamed('page2');
                    //IOS风格跳转
                    // Navigator.of(context).push(CupertinoPageRoute(
                    //     builder: (context) => const AnimationPage2()));
                    Navigator.of(context).push(PageRouteBuilder(
                        transitionDuration: const Duration(milliseconds: 500),
                        pageBuilder: (BuildContext context,
                            Animation<double> animation,
                            Animation<double> secondaryAnimation) {
                          return FadeTransition(
                            opacity: animation,
                            child: const AnimationPage2(),
                          );

                        }));
                  },
                )
              ],
            ),
          ),
        ),
      );
}

跳转的目标页面

class AnimationPage2 extends StatelessWidget {
  const AnimationPage2({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp(
        home: Scaffold(
          body: Center(
            child: Stack(
              alignment: Alignment.center,
              children: [
                Image.network(
                    'https://tse1-mm.cn.bing.net/th/id/R-C.40f1f5201a2c0d806a694dceeb057760?rik=79D7YC4k%2fkHsiQ&pid=ImgRaw&r=0'),
                ElevatedButton(
                  child: const Text('关闭'),
                  onPressed: () {
                    Navigator.pop(context);
                  },
                )
              ],
            ),
          ),
        ),
      );
}
main() {
  runApp(MaterialApp(
    // home: const AnimationPage1(),
    initialRoute: 'page1',
    routes: {
      'page1': (context) => const AnimationPage1(),
      'page2': (context) => const AnimationPage2(),
    },
  ));
}
 类似资料: