如何在Flutter上的页面加载时自动启动动画?

时间:2019-10-30 20:59:33

标签: flutter dart flutter-animation

我正在尝试在我的应用程序中实现启动屏幕页面。显示页面时,我需要自动启动动画,但实际的实现无法正常工作。动画不在打开页面时执行。

import 'package:flutter/material.dart';
import 'package:coin_flip_app/home_page.dart';
import 'package:flutter_svg/flutter_svg.dart';

class SplashScreenPage extends StatefulWidget {
  SplashScreenPage({Key key}) : super(key: key);

  @override
  _SplashScreenPageState createState() => _SplashScreenPageState();
}

class _SplashScreenPageState extends State<SplashScreenPage>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
        vsync: this, duration: Duration(milliseconds: 250), value: 1);

    Future.delayed(Duration(seconds: 4), () {
      Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => HomePage(),
          ));
    });

    _controller.forward().then((f) {
      _controller.reverse();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: const Color.fromARGB(255, 48, 48, 48),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RotationTransition(
              turns: Tween(begin: 0.0, end: 1.0).animate(_controller),
              child: SizedBox(
                child: SvgPicture.asset('assets/app_logo.svg'),
                height: 150,
              ),
            ),
            const Padding(
              padding: const EdgeInsets.only(top: 20.0),
              child: Text(
                "My App",
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 32,
                ),
                textAlign: TextAlign.center,
              ),
            )
          ],
        ),
      ),
    );
  }
}

如果我尝试使用带有GestureDetector的onTap()事件来调用动画,它将起作用。但是我需要它在没有用户输入的情况下自动启动并完成。

更新#1

这是更新的代码。它也不起作用。它只能在不注释第一个// await Future.delayed(Duration(seconds: 1));的情况下起作用,但我认为这只是一种解决方法,而不是最终解决方案

import 'package:flutter/material.dart';
import 'package:coin_flip_app/home_page.dart';
import 'package:flutter_svg/flutter_svg.dart';

class SplashScreenPage extends StatefulWidget {
  SplashScreenPage({Key key}) : super(key: key);

  @override
  _SplashScreenPageState createState() => _SplashScreenPageState();
}

class _SplashScreenPageState extends State<SplashScreenPage>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
        vsync: this, duration: Duration(milliseconds: 250), value: 1);

    WidgetsBinding.instance.addPostFrameCallback(
        (_) => loopOnce(context)); //i add this to access the context safely.
  }

  Future<void> loopOnce(BuildContext context) async {
    // await Future.delayed(Duration(seconds: 1));
    await _controller.forward();
    await _controller.reverse();
    //we can add duration here
    await Future.delayed(Duration(seconds: 1));
    Navigator.of(context).push(MaterialPageRoute(
      // since this triggers when the animation is done, no duration is needed
      builder: (context) => HomePage(),
    ));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: const Color.fromARGB(255, 48, 48, 48),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RotationTransition(
              turns: _controller,
              child: SizedBox(
                child: SvgPicture.asset('assets/app_logo.svg'),
                height: 150,
              ),
            ),
            const Padding(
              padding: const EdgeInsets.only(top: 20.0),
              child: Text(
                "My App",
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 32,
                ),
                textAlign: TextAlign.center,
              ),
            )
          ],
        ),
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:1)

很奇怪,也许尝试使用

imshow

代替

_controller.repeat(reverse: true);

哦,别忘了处置

_controller.forward().then((f) {
      _controller.reverse();
    });

您可以直接使用

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

编辑:

因此,如果我理解正确,您想这样做

向前循环然后向后循环一次, 循环结束后,导航至屏幕。

我的方法就是这个

RotationTransition(
              turns:_controller,
              child: SizedBox(
                child: SvgPicture.asset('assets/app_logo.svg'),
                height: 150,
              ),
            ),

编辑2:

@override
  void initState() {
    super.initState();
    _controller = AnimationController(
        vsync: this, duration: Duration(milliseconds: 250), value: 1);
    WidgetsBinding.instance.addPostFrameCallback((_)=>loopOnce(context));//i add this to access the context safely.
  }

  Future<void> loopOnce(BuildContext context)async{
    await _controller.forward();
    await _controller.reverse();
    //we can add duration here 
    //await Future.delayed(Duration(seconds: 4));
    Navigator.of(context).push(MaterialPageRoute( // since this triggers when the animation is done, no duration is needed
            builder: (context) => HomePage(),
          ));
  }