用NavigatorObserver动态改变页面过渡类型的Flutter GoRouter

kupeojn6  于 2023-03-13  发布在  Flutter
关注(0)|答案(1)|浏览(135)

我想动态更改用于在页面之间导航的过渡。
为此,我创建了一个枚举,它给出了两个不同的转换名称,例如TransitionType.fadeTransitionType.slide
然后我创建了一个围绕导航器的StatefulWidget,这个有状态的Widget会被更新以反映最顶端路径(isCurrent)的转换,所有页面都会跟随这个转换,状态可以随时更新。
然而,这似乎是不必要的复杂,我想知道这是否可以用NavigatorObserver来代替。所有的观察者必须做的是包含转换的状态,并允许在任何时候设置该状态。这可能吗?

nkoocmlb

nkoocmlb1#

我认为InheritedWidget将是代替NavigatorObserver的方法。
下面是一个实现GoRouterTransition小部件的代码示例,您可以使用GoRouterTransition.of(context)GoRouterTransition.maybeOf(context)访问该小部件,以读取和设置您的TransitionType(您必须将此小部件 Package 在您的MaterialApp之上):

class GoRouterTransition extends StatefulWidget {
  const GoRouterTransition({
    super.key,
    required this.child,
  });

  final Widget child;

  @override
  State<GoRouterTransition> createState() => GoRouterTransitionState();

  static GoRouterTransitionState? maybeOf(BuildContext context) {
    return context
        .dependOnInheritedWidgetOfExactType<_TransitionTypeScope>()
        ?.data;
  }

  static GoRouterTransitionState of(BuildContext context) {
    final state = maybeOf(context);
    assert(state != null, 'No GoRouterTransition found in context');
    return state!;
  }
}

class GoRouterTransitionState extends State<GoRouterTransition> {
  TransitionType _type = TransitionType.fade;
  TransitionType get type => _type;
  set type(TransitionType value) => setState(() => _type = value);

  @override
  Widget build(BuildContext context) {
    return _TransitionTypeScope(
      data: this,
      child: widget.child,
    );
  }
}

class _TransitionTypeScope extends InheritedWidget {
  const _TransitionTypeScope({
    required this.data,
    required super.child,
  });

  final GoRouterTransitionState data;

  @override
  bool updateShouldNotify(_TransitionTypeScope oldWidget) {
    return data.type != oldWidget.data.type;
  }
}

然后,您只需创建自己的自定义GoRoute对象,该对象将使用正确的过渡构建您的页面:

class DynamicGoRoute extends GoRoute {
  DynamicGoRoute({
    required super.path,
    required GoRouterWidgetBuilder builder,
    super.routes = const <RouteBase>[],
  }) : super(
          pageBuilder: (context, state) {
            final type = GoRouterTransition.of(context).type;

            switch (type) {
              case TransitionType.fade:
                return FadePage<void>(
                  builder: (context) => builder(context, state),
                );
              case TransitionType.slide:
                return SlidePage<void>(
                  builder: (context) => builder(context, state),
                );
            }
          },
        );
}

You can try the complete sample on zapp.run

相关问题