Как автоматически запустить анимацию при загрузке страницы на Flutter? - PullRequest
0 голосов
/ 30 октября 2019

Я пытаюсь реализовать страницу с заставкой в ​​моем приложении. Мне нужно автоматически запустить анимацию, когда страница отображается, но фактическая реализация не работает. Анимация не выполняется при открытии страницы.

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,
              ),
            )
          ],
        ),
      ),
    );
  }
}

Если я пытаюсь вызвать анимацию с событием onTap() с GestureDetector, она работает. Но мне нужно, чтобы он запускался и завершался без ввода пользователя, но автоматически.

ОБНОВЛЕНИЕ # 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 Ответ

1 голос
/ 31 октября 2019

Странно, может быть, попробуйте использовать

_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,
              ),
            ),

РЕДАКТИРОВАТЬ:

Так что, если я правильно понял, вы хотите сделать это

Цикл вперед и затем один раз, когда циклвсе готово, перейдите к экрану.

Мой метод будет такой

@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(),
          ));
  }

РЕДАКТИРОВАТЬ 2:

class Loader extends StatefulWidget {
  const Loader();
  @override
  _LoaderState createState() => _LoaderState();
}

class _LoaderState extends State<Loader> with SingleTickerProviderStateMixin {
  AnimationController _controller;

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

    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).pushNamed('');
  }

  @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: Container(
                width: 150,
                color: Colors.red,
                height: 150,
              ),
            ),
            const Padding(
              padding: const EdgeInsets.only(top: 20.0),
              child: Text(
                "Coin Flip",
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 32,
                ),
                textAlign: TextAlign.center,
              ),
            )
          ],
        ),
      ),
    );
}
}
...