简体   繁体   English

如何在没有动画的情况下导航到其他页面 Flutter

[英]How to navigate to other page without animation Flutter

I have a Login page, when I log on to go to the main page of my app i am using Navigator.pushReplacement(context, new MaterialPageRoute(builder: (BuildContext context) => new Page1()));我有一个登录页面,当我登录到我的应用程序的主页时,我正在使用Navigator.pushReplacement(context, new MaterialPageRoute(builder: (BuildContext context) => new Page1())); But it have the slide animation, i want to disable it.但它有幻灯片动画,我想禁用它。

this is my Material app format这是我的材料应用程序格式

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(),
      },
    );
  }
}

You can use PageRouteBuilder .您可以使用PageRouteBuilder

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

You would need to override the buildTransitions method to prevent animations.您需要覆盖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;
  }
}

For Null safety:对于 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;
  }
}

You can override MaterialPageRoute to set transitionDuration to zero:您可以覆盖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();
    },
  ),
);

Make sure you also set transitionDuration otherwise you may push the new route without animation but when you press back button, you'll see some delay.确保您还设置了transitionDuration否则您可能会在没有动画的情况下推送新路线,但是当您按下后退按钮时,您会看到一些延迟。

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

EDIT: This simple solution longer works.编辑:这个简单的解决方案更有效。 See https://github.com/flutter/flutter/issues/51649 .请参阅https://github.com/flutter/flutter/issues/51649

Good luck using the Navigator 2.0 API.祝您使用 Navigator 2.0 API 好运。


My solution is to define the route with isInitialRoute:true .我的解决方案是使用isInitialRoute:true定义路线。 This prevents Flutter from showing an animation when the route is pushed.这可以防止 Flutter 在推送路由时显示动画。

Here's a working example and screen recording:这是一个工作示例和屏幕录制:

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(),
                    ],
                  ),
                ),
              ),
            ),
      },
    ),
  );
}

录屏

You should try to extend MaterialPageRoute and override buildTransitions as follows:您应该尝试扩展 MaterialPageRoute 并覆盖 buildTransitions,如下所示:

class ExPageRoute<T> extends MaterialPageRoute<T> {

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

In case you would like to use a package, with the get package you can disable transition animations with a property of GetMaterialApp .如果您想使用包,可以使用get 包禁用带有GetMaterialApp属性的过渡动画。

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

And then just simply add the other desired properties.然后只需简单地添加其他所需的属性。

With Navigator 2.0, there are two ways:使用 Navigator 2.0,有两种方法:

  1. Rebuild the Navigator with a new pages list that has the last item replaced.使用替换了最后一项的新pages列表重建导航器。 If the previous Page and replacement Page both have no key or the same key, then Flutter will treat them as the same page and will not animate.如果之前的Page和替换Page都没有 key 或者 key 相同,那么 Flutter 会将它们视为同一个页面,不会进行动画处理。
  2. Set Navigator.transitionDelegate to an object that extends TransitionDelegate .Navigator.transitionDelegate设置为扩展TransitionDelegate的对象。 The delegate must check for a new record with RouteTransitionRecord.isWaitingForEnteringDecision true and call its markForAdd() method.委托必须使用RouteTransitionRecord.isWaitingForEnteringDecision true 检查新记录并调用其markForAdd()方法。 There is some useful code in https://github.com/flutter/flutter/issues/69315#issuecomment-833212172 . https://github.com/flutter/flutter/issues/69315#issuecomment-833212172中有一些有用的代码。

Example with navigator 2.0 without animation没有动画的 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;
  }
}

This is without transitions.这是没有过渡的。 Only Fade in next page仅淡入下一页

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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM