【问题标题】:Animation for named routes命名路线的动画
【发布时间】:2018-10-08 08:35:10
【问题描述】:

在 Flutter 中,我们可以通过扩展 PageRoute(或使用扩展它的类)来自定义视图更改动画。

例如,我通过使用CupertinoPageRouteMaterialApplication 中的动画更改为“幻灯片”:

Navigator.of(context).pushReplacement(
  CupertinoPageRoute(builder: (context) => Calendar()),
);

现在我想通过使用main.dart 文件中定义的命名视图来改变它:

return MaterialApp(
  title: 'Demo',
  theme: myTheme, // => Theme.of(context).copyWith(...)
  initialRoute: '/',
  routes: {
    '/': (context) => Login(),
    '/calendar': (context) => Calendar(),
  }
);

这样我就可以打电话了

Navigator.of(context).pushReplacementNamed('/calendar');

IMO 更清晰且与视图无关。

这种方法的问题是我无法定义PageRoute,因此我无法自定义视图更改动画。

有没有办法做到这一点?

【问题讨论】:

    标签: android animation routing flutter


    【解决方案1】:

    我接受了 chemamolins 的建议并以类似的方式解决了它,但使用了地图。

    我“提取”了routes 对象并将其放在MaterialApp 之外:

    var routes = {
      '/': (context) => Login(),
      '/calendar': (context) => Calendar()
    };
    

    然后我在onGenerateRoute里面使用了:

    Widget build(BuildContext context) {
      var routes = {
        '/': (context) => Login(),
        '/calendar': (context) => Calendar()
      };
    
      return MaterialApp(
        title: 'Demo',
        theme: myTheme,
        initialRoute: '/',
        onGenerateRoute: (settings) {
          return CupertinoPageRoute(builder: (context) => routes[settings.name](context));
        }
      );
    }
    

    【讨论】:

    • 对否决票的任何解释将不胜感激。
    • 很好,但是如何调用具有特定动画的页面?通过调用这个:Navigator.pushNamed(context, '/register'); 我只是得到一个向左滑动的动画,但是如果我想将它更改为向上/向右/....?
    • @Paul CupertinoPageRouteMaterialPageRoute 的行为与原生应用程序的行为相同,因此无法自定义动画方向。但是,您可以build your own animation 并完全根据需要进行操作。
    • 问题是我找不到使用命名路线自定义动画的机会。带有链接的动画:pageBuilder: (context, animation, secondaryAnimation) => const Page2() 有没有办法用路由名称调用下一页?
    【解决方案2】:

    您可以利用onGenerateRoute()

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      Route onGenerateRoute(RouteSettings settings) {
        Route page;
        switch (settings.name) {
          case "/":
            page = CupertinoPageRoute(builder: (context) => Login());
            break;
          case "/calendar":
            page = CupertinoPageRoute(builder: (context) => Calendar());
            break;
        }
        return page;
      }
    
      @override
      Widget build(BuildContext context) {
        return new WidgetsApp(
          onGenerateRoute: onGenerateRoute,
          initialRoute: "/",
        );
      }
    }
    

    让我们看一下 Flutter 代码本身。

    有一个框架提供的onGenerateRoute()方法被调用来生成路由。

    看下面从框架中的app.dart文件中提取的sn-p。

      Route<dynamic> _onGenerateRoute(RouteSettings settings) {
        final String name = settings.name;
        WidgetBuilder builder;
        if (name == Navigator.defaultRouteName && widget.home != null) {
          builder = (BuildContext context) => widget.home;
        } else {
          builder = widget.routes[name];
        }
        if (builder != null) {
          return new MaterialPageRoute<dynamic>(
            builder: builder,
            settings: settings,
          );
        }
        if (widget.onGenerateRoute != null)
          return widget.onGenerateRoute(settings);
        return null;
      }
    

    如果routes: 为给定名称提供构建器,则默认使用MaterialPageRoute 生成路由。如果没有提供,它会使用您的onGenerateRoute() 方法生成它。

    【讨论】:

    • 这不是一个小技巧吗?我的意思是,如果我必须在onGenerateRoute 方法中再次定义路由,定义路由的目的是什么?
    • 如果你想使用命名路由,我不认为这是一个 hack。在routes: 属性中您无法自定义路由,您只需通过构建器设置小部件即可。相比之下,在onGenerateRoute() 中,您可以自定义Route。假设您想使用默认的MaterialPageRoute 时,routes:onGenerateRoute: 的快捷方式。
    • 我已经编辑了我的答案,以解释如果 routes: 属性提供的内容不足以满足您的需求,为什么这不是黑客攻击。
    • 知道了。我是这样做的,但使用的是地图而不是开关盒。谢谢
    猜你喜欢
    • 2019-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多