【问题标题】:Start Widget Animation after Hero Animation has finishedHero Animation 完成后启动 Widget Animation
【发布时间】:2019-05-26 09:50:58
【问题描述】:

假设我有两个页面,Page1 和 Page2 包含一个英雄。在Page2中,我想在Hero动画完成后启动一个Widget动画。

是否可以通过回调在 Page2 中获得关于英雄动画状态的通知?

到目前为止,我发现的唯一解决方法是为 Widget 动画添加延迟,以避免它在 Hero 动画完成之前开始:

class Page1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) => Container(
        child: Hero(
          tag: "hero-tag",
          child: IconButton(
              icon: Icon(Icons.person),
              onPressed: () {
                Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (BuildContext context) => Page2(),
                    ));
              }),
        ),
      );
}

class Page2 extends StatefulWidget {
  @override
  _Page2State createState() => _Page2State();
}

class _Page2State extends State<Page2> with TickerProviderStateMixin {
  AnimationController _controller;
  Animation _fabAnimation;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
        duration: const Duration(milliseconds: 400), vsync: this);

    _fabAnimation = Tween<double>(
      begin: 0.0,
      end: 1.0,
    ).animate(
      CurvedAnimation(
        parent: _controller,

        // delay to wait for hero animation to end
        curve: Interval(
          0.300,
          1.000,
          curve: Curves.ease,
        ),
      ),
    );

    _controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Row(
        children: <Widget>[
          Hero(
            tag: "hero-tag",
            child: Icon(Icons.person),
          ),
          ScaleTransition(
            scale: _fabAnimation,
            child: FloatingActionButton(
              child: Icon(
                Icons.camera_alt,
              ),
              onPressed: () {},
            ),
          ),
        ],
      ),
    );
  }
}

【问题讨论】:

    标签: flutter flutter-animation


    【解决方案1】:

    好的,这是更好的答案。基于此处先前的答案。 Flutter: Run method on Widget build complete

    简答 我使用 WidgetsBinding 的 postFrameCallback() 测试了您的场景,如下所示,现在我认为相机图标上的补间动画在英雄动画完成后工作。您可以尝试将 _contoller.forward 包装在此回调中,如下所示。

    //this ensures the animation is forwarded only after the widget is rendered 
    //atleast one frame.
    
    // based on this answer: 
    //https://stackoverflow.com/questions/49466556/flutter-run-method-on-widget-build-complete
    
    WidgetsBinding.instance.addPostFrameCallback((_) {
    //Following future can be uncommented to check 
    //if the call back works after 5 seconds.
    //Future.delayed(const Duration(seconds: 5), () => {
      _controller.forward();
     //});
    });
    

    我也尝试了下面给出的 RouteAwareWidget 选项,但没有太大区别。 https://api.flutter.dev/flutter/widgets/RouteObserver-class.html

    完整的工作代码

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          //navigatorObservers: [routeObserver],
          initialRoute: '/',
          routes: {
            '/': (context) => Page1(),
            '/page2': (context) => Page2(),
          },
        );
      }
    }
    
    class Page1 extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Page 1'),
          ),
          body: Center(
            child: Hero(
              tag: "hero-tag",
              child: IconButton(
                  icon: Icon(Icons.person),
                  onPressed: () {
                    Navigator.pushNamed(context, '/page2');
                  }),
            ),
          ),
        );
      }
    }
    
    class Page2 extends StatefulWidget {
      @override
      _Page2State createState() => _Page2State();
    }
    
    class _Page2State extends State<Page2> with TickerProviderStateMixin {
      AnimationController _controller;
      Animation _fabAnimation;
    
      @override
      void initState() {
        super.initState();
        _controller = AnimationController(
            duration: const Duration(milliseconds: 400), vsync: this);
    
        _fabAnimation = Tween<double>(
          begin: 0.0,
          end: 1.0,
        ).animate(
          CurvedAnimation(
            parent: _controller,
    
            // delay to wait for hero animation to end
    //        curve: Interval(
    //          0.900,
    //          1.000,
            curve: Curves.ease,
            //),
          ),
        );
    
    // this ensures the animation is forwarded only after the widget is rendered 
    //atleast one frame.
    // based on: 
    //https://stackoverflow.com/questions/49466556/flutter-run-method-on-widget-build-complete
        WidgetsBinding.instance.addPostFrameCallback((_) {
          //Future.delayed(const Duration(seconds: 5), () =>
          _controller.forward();
          //);
        });
        //end
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('Screen 2')),
          body: Center(
            child: Row(
              children: <Widget>[
                Hero(
                  tag: "hero-tag",
                  child: Icon(Icons.person),
                ),
                ScaleTransition(
                  scale: _fabAnimation,
                  child: FloatingActionButton(
                    child: Icon(
                      Icons.camera_alt,
                    ),
                    onPressed: () {
                      Navigator.pop(
                        context,
                      ); // Added to avoid exceptions of no material widget.
                    },
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-05
      • 2012-12-21
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      • 2017-03-27
      相关资源
      最近更新 更多