Remplacer la Route initiale dans MaterialApp sans animation?

notre application est construite sur le dessus de Scaffold et à ce point nous avons été en mesure d'accommoder la plupart de nos exigences de routage et de navigation en utilisant les appels fournis dans NavigatorState (pushNamed(), pushReplacementNamed(), etc.). Ce que nous ne voulons pas, cependant, c'est avoir n'importe quelle sorte d'animation 'push' quand un utilisateur choisit un article de notre menu de tiroir (nav). Nous voulons l'écran de destination à partir d'un menu nav Cliquez pour devenir effectivement la nouvelle route initiale de la pile. Pour le moment nous utilisons pushReplacementNamed () pour s'assurer qu'il n'y a pas de flèche arrière dans la barre app. Mais, le glisser-dans-de-la-droit de l'animation implique une pile est la construction.

Quelle est notre meilleure option pour changer cette route initiale sans animation, et, pouvons-nous le faire tout en animant simultanément le tiroir fermé? Ou est-ce que nous regardons une situation où nous avons besoin de passer de navigateur plus à l'aide d'un seul échafaudage et la mise à jour du "corps" directement lorsque l'utilisateur veut changer les écrans?

Nous notons qu'il y est un replace() appeler NavigatorState ce qui, nous le pensons, pourrait être le bon endroit pour commencer à chercher, mais il n'est pas clair comment accéder à nos différentes routes originellement mises en place dans new MaterialApp(). Quelque chose comme replaceNamed() peut-être dans l'ordre ;-)

Merci d'avance!

16
demandé sur Eric Seidel 2017-04-28 16:02:07

2 réponses

Ce que vous faites sonne un peu comme un BottomNavigationBar, donc vous pourriez considérer un de ceux au lieu d'un Drawer.

cependant, ayant un seul Scaffold et la mise à jour du body quand l'utilisateur tape sur un élément de tiroir est une approche tout à fait raisonnable. Vous pourriez considérer un FadeTransition pour passer d'un corps à l'autre.

Ou, si vous le souhaitez à l'aide de Navigator mais ne voulez pas l'animation par défaut, vous pouvez personnaliser (ou désactiver) l'animation par s'étendant MaterialPageRoute. Voici un exemple:

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyCustomRoute<T> extends MaterialPageRoute<T> {
  MyCustomRoute({ WidgetBuilder builder, RouteSettings settings })
      : super(builder: builder, settings: settings);

  @override
  Widget buildTransitions(BuildContext context,
      Animation<double> animation,
      Animation<double> secondaryAnimation,
      Widget child) {
    if (settings.isInitialRoute)
      return child;
    // Fades between routes. (If you don't want any animation, 
    // just return child.)
    return new FadeTransition(opacity: animation, child: child);
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Navigation example',
      onGenerateRoute: (RouteSettings settings) {
        switch (settings.name) {
          case '/': return new MyCustomRoute(
            builder: (_) => new MyHomePage(),
            settings: settings,
          );
          case '/somewhere': return new MyCustomRoute(
            builder: (_) => new Somewhere(),
            settings: settings,
          );
        }
        assert(false);
      }
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Navigation example'),
      ),
      drawer: new Drawer(
        child: new ListView(
          children: <Widget> [
            new DrawerHeader(
              child: new Container(
                  child: const Text('This is a header'),
              ),
            ),
            new ListTile(
              leading: const Icon(Icons.navigate_next),
              title: const Text('Navigate somewhere'),
              onTap: () {
                Navigator.pushNamed(context, '/somewhere');
              },
            ),
          ],
        ),
      ),
      body: new Center(
        child: new Text(
          'This is a home page.',
        ),
      ),
    );
  }
}

class Somewhere extends StatelessWidget {
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Center(
        child: new Text(
          'Congrats, you did it.',
        ),
      ),
      appBar: new AppBar(
        title: new Text('Somewhere'),
      ),
      drawer: new Drawer(
        child: new ListView(
          children: <Widget>[
            new DrawerHeader(
              child: new Container(
                child: const Text('This is a header'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
28
répondu Collin Jackson 2017-04-28 19:36:25

Merci pour la réponse incroyablement utile, Collin!

un petit mod qui pourrait être utile parfois aussi: pour d'autres raisons je voulais une animation fade-in Quand mon écran (Échafaudage) arrivait, mais il était sur une pile et quand je sortais je voulais un slide-down régulier, comme il a été ajouté avec Navigator.pushReplacement(...). Incroyablement facile à réaliser:

class FadeInSlideOutRoute<T> extends MaterialPageRoute<T> {
  FadeInSlideOutRoute({WidgetBuilder builder, RouteSettings settings})
      : super(builder: builder, settings: settings);

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation, Widget child) {
    if (settings.isInitialRoute) return child;
    // Fades between routes. (If you don't want any animation,
    // just return child.)
    if (animation.status == AnimationStatus.reverse)
      return super.buildTransitions(context, animation, secondaryAnimation, child);
    return FadeTransition(opacity: animation, child: child);
  }
}
3
répondu gregko 2018-04-30 22:36:48