【问题标题】:Flutter | How to animate a widget upon navigation?颤振 |如何在导航时为小部件设置动画?
【发布时间】:2023-01-03 21:02:00
【问题描述】:

如何根据导航为小部件设置动画?

因为当它第一次创建时,我们可以使用 animationController.forward(); 在 initState 中。

但是其他转换呢:

  • 相同路线弹出
  • 新路由推送
  • 新路线流行

【问题讨论】:

    标签: flutter flutter-animation flutter-navigation


    【解决方案1】:

    采用路由观察者.

    final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();

    然后将其添加到根 materialApp 小部件:

    MaterialApp(
          theme: ThemeData(),
          navigatorObservers: [routeObserver],
    ) 
    

    (以上代码摘自here

    然后你可以为上面的任何项目控制你的 AnimationController。

    我的实现

    创建一个 RouteAware AnimationController 小部件并将控制器和子项传递给它。

    主要小部件构建:

    return RouteAwareAnimationController(
          controller: controller,
          child: SizeTransition( // Or any other animation that's connected to the controller
        
    

    RouteAwareAnimation 小部件

    class RouteAwareAnimationController extends StatefulWidget {
      const RouteAwareAnimationController({
        Key? key,
        required this.controller,
        required this.child,
      }) : super(key: key);
    
      final AnimationController controller;
      final Widget child;
    
      @override
      State<RouteAwareAnimationController> createState() => _RouteAwareAnimationControllerState();
    }
    
    class _RouteAwareAnimationControllerState extends State<RouteAwareAnimationController>
        with RouteAware {
      AnimationController get controller => widget.controller;
    
      @override
      Widget build(BuildContext context) {
        return widget.child;
      }
    
      @override
      void didChangeDependencies() {
        super.didChangeDependencies();
        routeObserver.subscribe(
            this, ModalRoute.of(context)! as PageRoute<dynamic>);
      }
    
      @override
      // page push, same as using this in initState
      void didPush() => controller.forward(); 
    
      @override
      // when this page is poped
      void didPop() => controller.reverse();
    
      @override
      // when next page is pushed
      void didPushNext() => controller.reverse();
    
      @override
      // when next page is poped
      void didPopNext() => controller.forward();
    
      @override
      void dispose() {
        routeObserver.unsubscribe(this);
    
        super.dispose();
      }
    }
    
    

    随意根据您的需要自定义它,或将 bool 值传递给它以启用或禁用某些操作。

    更通用的解决方案

    使用更通用的 RouteAwareWidget,以便您可以为每个特定的导航事件传递一个函数。

    它可能看起来像这样:

    class RouteAwareWidget extends StatefulWidget {
      const RouteAwareWidget({
        Key? key,
        required this.child,
        this.onPush,
        this.onPop,
        this.onPushNext,
        this.onPopNext,
      }) : super(key: key);
    
      final Widget child;
    
      final Function? onPush, onPop, onPushNext, onPopNext;
    
      @override
      State<RouteAwareWidget> createState() => _RouteAwareWidgetState();
    }
    
    class _RouteAwareWidgetState extends State<RouteAwareWidget> with RouteAware {
      @override
      Widget build(BuildContext context) {
        return widget.child;
      }
    
      @override
      void didChangeDependencies() {
        super.didChangeDependencies();
        routeObserver.subscribe(
            this, ModalRoute.of(context)! as PageRoute<dynamic>);
      }
    
      @override
      // page push, same as using this in initState
      void didPush() {
        if (widget.onPush != null) widget.onPush!();
      }
    
      @override
      // when this page is poped
      void didPop() {
        if (widget.onPop != null) widget.onPop!();
      }
    
      @override
      // when next page is pushed
      void didPushNext() {
        if (widget.onPushNext != null) widget.onPushNext!();
      }
    
      @override
      // when next page is poped
      void didPopNext() {
        if (widget.onPop != null) widget.onPopNext!();
      }
    
      @override
      void dispose() {
        routeObserver.unsubscribe(this);
    
        super.dispose();
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 2020-09-28
      • 1970-01-01
      • 2020-09-24
      • 2018-10-18
      • 1970-01-01
      • 2018-12-02
      相关资源
      最近更新 更多