【问题标题】:How to navigate to other page without animation Flutter如何在没有动画的情况下导航到其他页面 Flutter
【发布时间】:2018-09-27 04:39:55
【问题描述】:

我有一个登录页面,当我登录到我正在使用的应用程序的主页时 Navigator.pushReplacement(context, new MaterialPageRoute(builder: (BuildContext context) => new Page1())); 但它有幻灯片动画,我想禁用它。

这是我的 Material 应用格式

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new Login(title: 'Login'),
      routes: <String, WidgetBuilder>{
        '/screen3': (BuildContext context) => new Page1(),
      },
    );
  }
}

【问题讨论】:

  • 您的意思是要在没有新页面/路由的情况下更改页面内容
  • 它可以工作,但我的意思是导航到没有导航动画的清理堆栈的页面。

标签: navigation flutter


【解决方案1】:

您可以使用PageRouteBuilder

Navigator.pushReplacement(
    context, 
    PageRouteBuilder(
        pageBuilder: (context, animation1, animation2) => Page1(),
        transitionDuration: Duration.zero,
        reverseTransitionDuration: Duration.zero,
    ),
);

【讨论】:

  • 添加transitionDuration: Duration(seconds: 0),立即进行过渡。
  • 添加 reverseTransitionDuration: Duration.zero 不会延迟弹出!
【解决方案2】:

您需要重写 buildTransitions 方法来阻止动画。

import 'package:flutter/material.dart';

class NoAnimationMaterialPageRoute<T> extends MaterialPageRoute<T> {
  NoAnimationMaterialPageRoute({
    @required WidgetBuilder builder,
    RouteSettings settings,
    bool maintainState = true,
    bool fullscreenDialog = false,
  }) : super(
            builder: builder,
            maintainState: maintainState,
            settings: settings,
            fullscreenDialog: fullscreenDialog);

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation, Widget child) {
    return child;
  }
}

对于 Null 安全性:

import 'package:flutter/material.dart';

class NoAnimationMaterialPageRoute<T> extends MaterialPageRoute<T> {
  NoAnimationMaterialPageRoute({
    required WidgetBuilder builder,
    RouteSettings? settings,
    bool maintainState = true,
    bool fullscreenDialog = false,
  }) : super(
            builder: builder,
            maintainState: maintainState,
            settings: settings,
            fullscreenDialog: fullscreenDialog);

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation, Widget child) {
    return child;
  }
}

【讨论】:

【解决方案3】:

您可以覆盖MaterialPageRoute 以将transitionDuration 设置为零:

class CustomPageRoute extends MaterialPageRoute {
  CustomPageRoute({builder}) : super(builder: builder);

  @override
  Duration get transitionDuration => const Duration(milliseconds: 0);
}

...

Navigator.of(context).push(
  CustomPageRoute(
    builder: (BuildContext context) {
      return DashboardView();
    },
  ),
);

【讨论】:

  • 这个解决方案也可以用于 pushNamed 吗?如果有,怎么做?
【解决方案4】:

确保您还设置了transitionDuration,否则您可能会在没有动画的情况下推送新路线,但是当您按下返回按钮时,您会看到一些延迟。

Navigator.push(
  context,
  PageRouteBuilder(
    pageBuilder: (_, __, ___) => Screen2(),
    transitionDuration: const Duration(seconds: 0),
  ),
);

【讨论】:

  • 这是正确的,持续时间为零秒方法我们在关闭路线上得到延迟。而且看起来很烦人。
  • 还有reverseTransitionDuration,也可以设置为0
【解决方案5】:

我的解决方案是使用isInitialRoute:true 定义路由。这样可以防止 Flutter 在推送路由时显示动画。

这是一个工作示例和屏幕录制:

import 'package:flutter/cupertino.dart'
    show
        CupertinoApp,
        CupertinoButton,
        CupertinoPageRoute,
        CupertinoPageScaffold;
import 'package:flutter/widgets.dart'
    show
        BuildContext,
        Center,
        Column,
        Navigator,
        Route,
        RouteSettings,
        SafeArea,
        Spacer,
        Text,
        runApp,
        Widget;

Widget makeButton(BuildContext context, String routeName) =>
    new CupertinoButton(
      onPressed: () => Navigator.pushReplacementNamed(context, routeName),
      child: Text('Go to \'$routeName\''),
    );

Route generateRoute(RouteSettings settings) {
  switch (settings.name) {
    case 'not-animated':
      return new CupertinoPageRoute(
        settings: RouteSettings(name: settings.name, isInitialRoute: true),
        builder: (context) => CupertinoPageScaffold(
              child: SafeArea(
                child: Center(
                  child: Column(
                    children: [
                      Spacer(),
                      Text('This is \'not-animated\''),
                      makeButton(context, 'animated'),
                      Spacer(),
                    ],
                  ),
                ),
              ),
            ),
      );
    default:
      return null;
  }
}

void main() {
  runApp(
    CupertinoApp(
      onGenerateRoute: generateRoute,
      initialRoute: 'animated',
      routes: {
        'animated': (context) => CupertinoPageScaffold(
              child: SafeArea(
                child: Center(
                  child: Column(
                    children: [
                      Spacer(),
                      Text('This is \'animated\''),
                      makeButton(context, 'not-animated'),
                      Spacer(),
                    ],
                  ),
                ),
              ),
            ),
      },
    ),
  );
}

【讨论】:

  • 实现简单结果的最简单方法:不使用动画导航。谢谢!
  • 我认为这个解决方案不适用于 pop 或 popUntil?
  • 杰出而简单,非常感谢!它在 Flutter 1.12.13+hotfix.8 中完美运行。
  • isInitialRoute 已被移除 (github.com/flutter/flutter/issues/51649)
【解决方案6】:

如果您想使用包,可以使用 get package 禁用属性为 GetMaterialApp 的过渡动画。

GetMaterialApp(
  defaultTransition: Transition.noTransition, //this would be the solution
  transitionDuration: transitionDuration: Duration(seconds: 0),
);

然后只需简单地添加其他所需的属性。

【讨论】:

    【解决方案7】:

    您应该尝试扩展 MaterialPageRoute 并覆盖 buildTransitions,如下所示:

    class ExPageRoute<T> extends MaterialPageRoute<T> {
    
     @override
     Widget buildTransitions(BuildContext context, Animation<double> animation,
        Animation<double> secondaryAnimation, Widget child) {
        return child;
     }
    }
    

    【讨论】:

    • builder 不见了。
    【解决方案8】:

    使用 Navigator 2.0,有两种方法:

    1. 使用替换了最后一项的新pages 列表重建导航器。如果之前的Page和替换的Page都没有key或者key相同,那么Flutter会把它们当作同一个页面,不会动画。
    2. Navigator.transitionDelegate 设置为扩展TransitionDelegate 的对象。委托必须使用RouteTransitionRecord.isWaitingForEnteringDecision true 检查新记录并调用其markForAdd() 方法。 https://github.com/flutter/flutter/issues/69315#issuecomment-833212172 中有一些有用的代码。

    【讨论】:

      【解决方案9】:

      没有动画的 navigator 2.0 示例

      import 'package:flutter/material.dart';
      
      void main() {
        runApp(const MyApp());
      }
      
      var userName = '';
      var password = '';
      
      class MyApp extends StatelessWidget {
        const MyApp({Key? key}) : super(key: key);
      
        @override
        Widget build(context) {
          return MaterialApp(
            home: Navigator(
              transitionDelegate: NoAnimationTransitionDelegate(),
              pages: [
                MaterialPage(child: HomePage()),
                if (password.isEmpty) MaterialPage(child: PasswordPage()),
                if (userName.isEmpty) MaterialPage(child: UserNamePage()),
              ],
              onPopPage: (route, result) {
                if (!route.didPop(result)) return false;
                return true;
              },
            ),
          );
        }
      }
      
      class HomePage extends StatelessWidget {
        @override
        Widget build(context) {
          return Scaffold(backgroundColor: Colors.blue);
        }
      }
      
      class PasswordPage extends StatelessWidget {
        @override
        Widget build(context) {
          return Scaffold(backgroundColor: Colors.amber);
        }
      }
      
      class UserNamePage extends StatelessWidget {
        @override
        Widget build(context) {
          return Scaffold(backgroundColor: Colors.green);
        }
      }
      
      class NoAnimationTransitionDelegate extends TransitionDelegate<void> {
        @override
        Iterable<RouteTransitionRecord> resolve({
          required List<RouteTransitionRecord> newPageRouteHistory,
          required Map<RouteTransitionRecord?, RouteTransitionRecord> locationToExitingPageRoute,
          required Map<RouteTransitionRecord?, List<RouteTransitionRecord>> pageRouteToPagelessRoutes,
        }) {
          final results = <RouteTransitionRecord>[];
      
          for (final pageRoute in newPageRouteHistory) {
            if (pageRoute.isWaitingForEnteringDecision) {
              pageRoute.markForAdd();
            }
            results.add(pageRoute);
          }
      
          for (final exitingPageRoute in locationToExitingPageRoute.values) {
            if (exitingPageRoute.isWaitingForExitingDecision) {
              exitingPageRoute.markForRemove();
              final pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute];
              if (pagelessRoutes != null) {
                for (final pagelessRoute in pagelessRoutes) {
                  pagelessRoute.markForRemove();
                }
              }
            }
            results.add(exitingPageRoute);
          }
      
          return results;
        }
      }
      

      【讨论】:

        【解决方案10】:

        这是没有过渡的。只淡入下一页

        class FadeInPageRoute<T> extends PageRoute<T> {
          FadeInPageRoute({
            RouteSettings? settings,
            required this.builder,
          }) : super(settings: settings);
        
          final WidgetBuilder builder;
        
          @override
          Color get barrierColor => Colors.black;
        
          @override
          String get barrierLabel => '';
        
          @override
          Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
            return builder(context);
          }
        
          @override
          bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
            return false;
          }
        
          @override
          Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
            return Opacity(
              opacity: animation.value,
              child: builder(context),
            );
          }
        
          @override
          bool get maintainState => true;
        
          @override
          Duration get transitionDuration => Duration(milliseconds: 700);
        }
        
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-07-29
          • 2022-01-06
          • 2020-07-29
          • 2022-11-01
          • 2020-10-10
          • 1970-01-01
          • 2020-07-31
          相关资源
          最近更新 更多