Easy-to-use Navigator 2.0 router for web, mobile and desktop. URL-based routing, simple navigation of tabs and nested routes.

Overview

Routemaster

Hello! Routemaster is an easy-to-use router for Flutter, which wraps over Navigator 2.0... and has a silly name.

Build codecov pub

Features

  • Simple declarative mapping from URLs to pages
  • Easy-to-use API: just Routemaster.of(context).push('/page')
  • Really easy nested navigation support for tabs
  • Multiple route maps: for example one for a logged in user, another for logged out
  • Observers to easily listen to route changes
  • Covered by over 250 unit, widget and integration tests

Here's the entire routing setup needed for an app featuring tabs and pushed routes:

final routes = RouteMap(
  routes: {
    '/': (_) => CupertinoTabPage(
          child: HomePage(),
          paths: ['/feed', '/settings'],
        ),

    '/feed': (_) => MaterialPage(child: FeedPage()),
    '/settings': (_) => MaterialPage(child: SettingsPage()),
    '/feed/profile/:id': (info) => MaterialPage(
      child: ProfilePage(id: info.pathParameters['id'])
    ),
  }
);

void main() {
  runApp(
      MaterialApp.router(
        routerDelegate: RoutemasterDelegate(routesBuilder: (context) => routes),
        routeInformationParser: RoutemasterParser(),
      ),
  );
}

And then to navigate:

Routemaster.of(context).push('/feed/profile/1');

...you can see this in action in this simple app example.

There's also a more advanced example.

I would love any feedback you have! Please create an issue for API feedback.

Documentation

Begin with the quick start below, but also see the API reference, wiki and FAQs.


Quick start API tour

Overview

Routemaster generates pages based on the current path. This is the key concept of its path-base routing. Path structure matters.

It uses the path to decide where a page should be pushed. This means the path needs to match your intended page hierarchy.

For example:

'/tabs': (route) => TabPage(child: HomePage(), paths: ['one', 'two']),

// First tab default page
'/tabs/one': (route) => MaterialPage(child: TabOnePage()),

// Second tab default page
'/tabs/two': (route) => MaterialPage(child: TabTwoPage()),

// Second tab sub-page: will be displayed in the 2nd tab because it
// starts with '/tabs/two'
'/tabs/two/subpage': (route) => MaterialPage(child: TabTwoPage()),

// Not a tab page: will not be displayed in in a tab
// because the path doesn't start with '/tabs/one' or '/tabs/two'
'/tabs/notInATab': (route) => MaterialPage(child: NotTabPage()),

Any child paths that begin with /tabs/one or /tabs/two will be pushed into the correct tab.

When navigating to /tabs/two/subpage, the TabPage will be asked "hey, do you know how to handle this path?" and it'll go "sure! it starts with /tabs/two, so it goes in my second tab".

However, navigating to /tabs/notInATab will not be displayed in a tab, but pushed on top of the tab bar.

TabPage will be all "yeah sorry, no idea what to do with that, doesn't match any of my tab paths" and its parent will be asked to hande it.

Path hierarchy matters, for example changing where dialogs are displayed.

Routing

Basic app routing setup

MaterialApp.router(
  routerDelegate: RoutemasterDelegate(
    routesBuilder: (context) => RouteMap(routes: {
      '/': (routeData) => MaterialPage(child: PageOne()),
      '/two': (routeData) => MaterialPage(child: PageTwo()),
    }),
  ),
  routeInformationParser: RoutemasterParser(),
)

Navigate from within pages

Routemaster.of(context).push('relative-path');
Routemaster.of(context).push('/absolute-path');

Routemaster.of(context).replace('relative-path');
Routemaster.of(context).replace('/absolute-path');

Path parameters

// Path '/products/123' will result in ProductPage(id: '123')
RouteMap(routes: {
  '/products/:id': (route) => MaterialPage(
        child: ProductPage(id: route.pathParameters['id']),
      ),
  '/products/myPage': (route) => MaterialPage(MyPage()),
})

Note that routes without path parameters have priority, so in the above example /products/myPage will show MyPage.

Query parameters

// Path '/search?query=hello' results in SearchPage(query: 'hello')
RouteMap(routes: {
  '/search': (route) => MaterialPage(
        child: SearchPage(query: route.queryParameters['query']),
      ),
})

Get current path info within a widget

RouteData.of(context).path; // Full path: '/product/123?query=param'
RouteData.of(context).pathParameters; // Map: {'id': '123'}
RouteData.of(context).queryParameters; // Map: {'query': 'param'}

Tabs

Setup:

RouteMap(
  routes: {
    '/': (route) => TabPage(
          child: HomePage(),
          paths: ['/feed', '/settings'],
        ),
    '/feed': (route) => MaterialPage(child: FeedPage()),
    '/settings': (route) => MaterialPage(child: SettingsPage()),
  },
)

Main page:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final tabPage = TabPage.of(context);

    return Scaffold(
      appBar: AppBar(
        bottom: TabBar(
          controller: tabPage.controller,
          tabs: [
            Tab(text: 'Feed'),
            Tab(text: 'Settings'),
          ],
        ),
      ),
      body: TabBarView(
        controller: tabPage.controller,
        children: [
          for (final stack in tabPage.stacks) PageStackNavigator(stack: stack),
        ],
      ),
    );
  }
}

Cupertino tabs

Setup:

RouteMap(
  routes: {
    '/': (route) => CupertinoTabPage(
          child: HomePage(),
          paths: ['/feed', '/settings'],
        ),
    '/feed': (route) => MaterialPage(child: FeedPage()),
    '/settings': (route) => MaterialPage(child: SettingsPage()),
  },
)

Main page:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final tabState = CupertinoTabPage.of(context);

    return CupertinoTabScaffold(
      controller: tabState.controller,
      tabBuilder: tabState.tabBuilder,
      tabBar: CupertinoTabBar(
        items: [
          BottomNavigationBarItem(
            label: 'Feed',
            icon: Icon(CupertinoIcons.list_bullet),
          ),
          BottomNavigationBarItem(
            label: 'Settings',
            icon: Icon(CupertinoIcons.search),
          ),
        ],
      ),
    );
  }
}

Guarded routes

Show default not found page if validation fails:

'/protected-route': (route) => 
    canUserAccessPage()
      ? MaterialPage(child: ProtectedPage())
      : NotFound()

Redirect to another page if validation fails (changes URL):

'/protected-route': (route) => 
    canUserAccessPage()
      ? MaterialPage(child: ProtectedPage())
      : Redirect('/no-access'),

Show another page if validation fails (doesn't change URL):

'/protected-route': (route) => 
    canUserAccessPage()
      ? MaterialPage(child: ProtectedPage())
      : MaterialPage(child: CustomNoAccessPage())

404 Page

Default page to shown on unknown URL:

RouteMap(
    onUnknownRoute: (route, context) {
        return MaterialPage(child: NotFoundPage());
    },
    routes: {
        '/': (_) => MaterialPage(child: HomePage()),
    },
)

Redirect

Redirect one route to another:

RouteMap(routes: {
    '/one': (routeData) => MaterialPage(child: PageOne()),
    '/two': (routeData) => Redirect('/one'),
})

Redirect all routes to login page, for a logged-out route map:

RouteMap(
  onUnknownRoute: (_) => Redirect('/'),
  routes: {
    '/': (_) => MaterialPage(child: LoginPage()),
  },
)

Passing path parameters from original to the redirect path:

RouteMap(routes: {
    '/user/:id': (routeData) => MaterialPage(child: UserPage(id: id)),
    '/profile/:uid': (routeData) => Redirect('/user/:uid'),
})

Swap routing map

You can swap the entire routing map at runtime.

This is particularly useful for different pages depending on whether the user is logged in:

final loggedOutMap = RouteMap(
  onUnknownRoute: (route, context) => Redirect('/'),
  routes: {
    '/': (_) => MaterialPage(child: LoginPage()),
  },
);

final loggedInMap = RouteMap(
  routes: {
    // Regular app routes
  },
);

MaterialApp.router(
  routerDelegate: RoutemasterDelegate(
    routesBuilder: (context) {
			// This will rebuild when AppState changes
      final appState = Provider.of<AppState>(context);
      return appState.isLoggedIn ? loggedInMap : loggedOutMap;
    },
  ),
  routeInformationParser: RoutemasterParser(),
);

Navigation observers

class MyObserver extends RoutemasterObserver {
	// RoutemasterObserver extends NavigatorObserver and
	// receives all nested Navigator events
  @override
  void didPop(Route route, Route? previousRoute) {
    print('Popped a route');
  }

	// Routemaster-specific observer method
  @override
  void didChangeRoute(RouteData routeData, Page page) {
    print('New route: ${routeData.path}');
  }
}

MaterialApp.router(
  routerDelegate: RoutemasterDelegate(
    observers: [MyObserver()],
    routesBuilder: (_) => routeMap,
  ),
  routeInformationParser: RoutemasterParser(),
);

Navigate without a context

app.dart

final routemaster = RoutemasterDelegate(
  routesBuilder: (context) => routeMap,
);

MaterialApp.router(
  routerDelegate: routemaster,
  routeInformationParser: RoutemasterParser(),
)

my_widget.dart

import 'app.dart';

void onTap() {
  routemaster.push('/blah');
}

Hero animations

Hero animations will work automatically on the top-level navigator (assuming you're using MaterialApp or CupertinoApp).

For any child navigators, you'll need to wrap PageStackNavigator in a HeroControllerScope, like this:

HeroControllerScope(
  controller: MaterialApp.createMaterialHeroController(),
  child: PageStackNavigator(
    stack: pageStack,
  )
)

Design goals

  • Integrated: work with the Flutter Navigator 2.0 API, don't try to replace it. Try to have a very Flutter-like API.
  • Usable: design around user scenarios/stories, such as the ones in the Flutter storyboard - see here for examples.
  • Opinionated: don't provide 10 options to achieve a goal, but be flexible for all scenarios.
  • Focused: just navigation, nothing else. For example, no dependency injection.

This project builds on page_router.

Name

Named after the original Routemaster:

A photo of a Routemaster bus

(photo by Chris Sampson, licensed under CC BY 2.0)

Comments
  • Page not pushed or replaced if on the same path pattern

    Page not pushed or replaced if on the same path pattern

    Given this fragment /detail/:id/equipment/:eqId. I need to loop over this path with eqId change.

    Route is correctly matched and returns the page with correct args but the page nevers shows.

    Also navigation is broken after this. pop doesn't pop to '/detail/:id' but to '/'.

    opened by bdremynoel 18
  • How to push full screen page on path of tab page?

    How to push full screen page on path of tab page?

    '/ei': (route) {
      return TabPage(
          child: MyPage(),
          paths: ['res'],
      );
    },
    '/ei/res/:id': (route) {
       // This route automatically nested but I don't want to.
    },
    ...
    

    res tab page shows list, the other route '/ei/res/:id' is for detail. I need to get it full screen to avoid user navigation mistake when editing data.

    • Changing route prefix is not an option, since I need deep linking too.
    • Can't be anonymous either...

    Any way to achieve this?

    documentation awaiting response 
    opened by bdremynoel 15
  • Pages get rebuilt when not needed with PageStackNavigator in v0.8.0

    Pages get rebuilt when not needed with PageStackNavigator in v0.8.0

    Pages get rebuilt in v0.8.0 with PageStackNavigator. This does not happen with v0.7.2 and StackNavigator. E.g. when using StatefulWidget for a page, initState is called again and everything is rebuilt from scratch, even when it should not be.

    I do not get this rebuild if I downgrade to v 0.7.2 with the same project, but with v0.8.0 I get them. The only change between the builds is changing from StackNavigator to PageStackNavigator.

    If I use the deprecated name/version StackNavigator with v0.8.0 the extra rebuild still happens. A downgrade to version 0.7.2 is required to avoid it and to get things working as before.

    Sorry I have not looked into the issue enough yet to have minimum repeatable case. I might post an example later.

    bug performance 
    opened by rydmike 15
  • Stacked pages hierarchy rebuilt on push of relative child route

    Stacked pages hierarchy rebuilt on push of relative child route

    I'm trying to make sense of some page rebuilding going on. Not sure if it's a by design thing or a bug at this point.

    I've created a fork and added a new example app here. All this app provides are 4 pages, each with a button that when clicked will navigate to one of the other pages; page1->page2->page3->page4. The navigation is by pushing a relative path and the routes are as follows:

            '/one/:p1': (_) {
              print("Creating MaterialPageOne");
              return const MaterialPageOne();
            },
            '/one/:p1/two/:p2': (_) {
              print("Creating MaterialPageTwo");
              return const MaterialPageTwo();
            },
            '/one/:p1/two/:p2/three/:p3': (_) {
              print("Creating MaterialPageThree");
              return const MaterialPageThree();
            },
            '/one/:p1/two/:p2/three/:p3/four/:p4': (_) {
              print("Creating MaterialPageFour");
              return const MaterialPageFour();
            },
            '/': (_) => const Redirect('/one/1'),
    

    In my fork I've added some print statements so I can see what the current page stack is when routing occurs. With this configuration I only ever see a single page in the stack (during routemaster's _navigate method here) no matter what level of nesting there is. Consequently, I also notice the Build method of each page in the hierarchy being called, sometimes as a result of the route builder for the page being called but sometimes without.

    This is an example of the console output I see from my print statements: On startup we see the following:

    I/flutter (27017): Creating MaterialPageOne
    I/flutter (27017): PageOne build
    

    Nothing wrong there. Next, tap "page-2" button to navigate to page 2 from page 1:

    I/flutter (27017): Routemaster page stack: [0] -> /one/1
    I/flutter (27017): Creating MaterialPageTwo
    I/flutter (27017): PageTwo build
    I/flutter (27017): PageOne build
    

    Expected the page 2 create call from the route builder but not page1's rebuild. Then from page 2 to page 3 we see:

    I/flutter (27017): Routemaster page stack: [0] -> /one/1/two/2
    I/flutter (27017): Creating MaterialPageThree
    I/flutter (27017): Creating MaterialPageOne
    I/flutter (27017): PageThree build
    I/flutter (27017): PageOne build
    I/flutter (27017): PageTwo build
    

    Expected the page 3 create call from the route builder but didn't expect to see page 1 being entirely recreated. I suspect it's related to the current page stack only containing page2? Add to that we also see a rebuild of page 2 - page1 build is due to the page being created again.

    Is this behaviour by design or a bug? I was really hoping that if I push a relative path that the previous page hierarchy would not be recreated or rebuilt.

    bug 
    opened by markphillips100 13
  • TabPage navigation

    TabPage navigation

    Here's the related routing for the current issue.

    // A tab page , as my main page
    '/ei/:eiId': (route) {
     return TabPage(..., paths: [..., 'list'])
    }
    // Nested page from tab page
    '/ei/:eiId/list': (route) {
     return MaterialPage(...)
    }
    // A full page
    '/ei/:eiId/sub/sub/:anotherId': (route) {
     return MaterialPage(...)
    }
    

    Route '/ei/:eiId/sub/sub/:anotherId' pushes '/ei/:eiId/list'.

    ~~When~~ Land~~ing~~ directly on '/ei/:eiId/sub/sub/:anotherId'~~, route '/ei/:eiId' is not build "completely" before this page, I can see it with inherited theme not applied.~~ When route '/ei/:eiId/list' is pushed, the URL is fine but the TabPage is broken, the listing tab doesn't show and tab navigation does not work. If I refresh the page, the navigation gets back to normal and I get the listing page.

    I just tried to wrap TabPage with StackPage in 0.10, but this does not change the behaviour.

    For now, I must manually push '/ei/:eiId', wait few milliseconds, and replace with the listing page.

    bug awaiting response 
    opened by bdremynoel 12
  • mobile_app demo doesn't stay logged in when manually changing URL

    mobile_app demo doesn't stay logged in when manually changing URL

    In the routemaster bundled example mobile_app that uses:

    Routemaster.setPathUrlStrategy();

    When the app is built as a Web Chrome target in development mode, entering a URLs causes the app to reload entirely and it starts from login again.

    If you remove Routemaster.setPathUrlStrategy(); and keep the Flutter default silly (well none web standard anyway, nobody wants it) hash/number sign '#' strategy, it all works OK.

    Can this silliness be fixed or is yet another Flutter Web SPA PWA "feature"? If that is the case, then the Routemaster.setPathUrlStrategy(); is pretty useless (but not routemaster's fault of course) and then # just have to be used.

    Perhaps it works with Routemaster.setPathUrlStrategy(); if you deploy the mobile_app demo on a server. I did not try that yet. If so, that still means you would have to limit Routemaster.setPathUrlStrategy(); to server deployments and cannot use it in dev mode.

    demo app issue 
    opened by rydmike 12
  • Return values

    Return values

    With the classic Navigator, you can return values from pushes:

    final result = await Navigator.of(context).pushNamed('route'); Navigator.of(context).pop('result');

    Currently, Routemaster has no support for this.

    Questions

    1. Is this something worth adding? How popular is this?
    2. Can this actually be done with Navigator 2.0 and global routing?

    If this isn't added, there should be documentation on how to pass values to previous pages.

    enhancement API design 
    opened by tomgilder 10
  • navigator key added

    navigator key added

    It is related to this issue: https://github.com/tomgilder/routemaster/issues/195 I sent a pull request earlier but it has conflicts with main branch. so I send another PR regarding that issue (sorry for the delay)

    opened by xoltawn 9
  • Routemaster conflicts with url_strategy

    Routemaster conflicts with url_strategy

    I have created a splash screen kinda thing and in it's initState I am adding a timer and moving to next screen after 1 second it should move to next screen, however, it doesn't move to the next screen when using replace()

    opened by AbhishekDoshi-Bacancy 9
  • Scenario: popping multiple pages

    Scenario: popping multiple pages

    Pages A, B and C are on the navigation stack. User is on page C at path /a/b/c.

    We want to pop back to page A... how? Answer: push('/a') - but that feels weird.

    From a user's perspective, it feels like you want to call popTo('/a').

    Needs documentation and/or better API.

    enhancement API design scenario 
    opened by tomgilder 9
  • navigator key in routerdelegate

    navigator key in routerdelegate

    Hi! I was wondering why navigator key is not added to routerdelegate? It can really come in handy where you need context but you don't have access to context directly. for example showing a dialog, etc. I've added it in my local repository, I can PR if you want

    opened by xoltawn 7
  • onUnknownRoute callback is not invoked correctly

    onUnknownRoute callback is not invoked correctly

    If I register a route "baseURL/home/:id/details". Then the package will not invoke onUnknownRoute() callback when I try to access "baseURL/home/random_text".

    opened by dbspoudel 0
  • There is no wait for a route to get over and execute something after that

    There is no wait for a route to get over and execute something after that

    Convential navigator allows you to add a callback method to Navigator.push().whenComplete(). It would be great to have something like that for routemaster

    opened by devout-coder 0
  • When opening URL directly takes users to /

    When opening URL directly takes users to /

    Inside app URLs working fine but when I try open a link directly browser like test.web.app/home/ad/45Ui2I0I8283CgLGlYBh user is being redirected to route '/'.

    I'm not sure it's a bug but I need this feature in order to share links.

    Routes

    routes: { '/': () => const MaterialPage(child: Splash()), '/$loginRoute' : () => const MaterialPage(child: Login()), '/$welcomeRoute': () => const MaterialPage(child: OnBoarding()), '/$homeRoute': () => const MaterialPage(child: Dashboard()), '/$homeRoute/$jobRoute': () => const MaterialPage(child: EmptyScreen(title: jobRoute,)), '/$homeRoute/$adsRoute': () => const MaterialPage(child: EmptyScreen(title: adsRoute,)), '/$homeRoute/$languageRoute': () => const MaterialPage(child: LanguageScreen()), '/$homeRoute/$profileRoute': () => const MaterialPage(child: MyProfile()), '/$homeRoute/$profileRoute/$editRoute': () => MaterialPage(child: EditProfile()), '/$homeRoute/$profileRoute/$adSettingsRoute': () => const MaterialPage(child: AdSettings()), '/$homeRoute/$profileRoute/$bankInfoRoute': () => const MaterialPage(child: EmptyScreen(title: bankInfoRoute,)), '/$homeRoute/$profileRoute/$paymentRoute': () => const MaterialPage(child: EmptyScreen(title: paymentRoute,)), '/$homeRoute/$profileRoute/$languageRoute': (_) => const MaterialPage(child: LanguageScreen()), '/$homeRoute/$newAdRoute': (info) => MaterialPage(child: CreateAd(hero: info.queryParameters["signature"] ?? UniqueKey().toString())), '/$homeRoute/user/:id': (info) => MaterialPage( child: UserView(name: info.pathParameters['id'] ?? "",) ), '/$homeRoute/$adRoute/:id':(info) => MaterialPage(child: AdDetail(adId: info.pathParameters['id'] ?? "",)) }

    opened by rafid-nsv 0
  • Update `nested` branch to latest `main` changes

    Update `nested` branch to latest `main` changes

    At first thank you so much @tomgilder for this awesome package!

    I got so much positive feedback from my collegues and they love it!

    There were some crucial changes came in to latest Flutter and latest main branch that I had to update everything in the nested branch to be able to use widget_navigator today.

    This PR updates the nested branch for the WidgetNavigator on StackPages.

    opened by Ahmadre 0
  • tutorials on how to use routemaster?

    tutorials on how to use routemaster?

    love the package and would love to see more youtube tutorials on how to use it.. I have only found one though it is a very long tutorial and most people get lost in the process.. https://www.youtube.com/watch?v=B8Sx7wGiY-s&t=86s .. by the way you should use it in your references as an example of a very complex app that works with routemaster..

    opened by abcnow 0
Releases(v0.10.0-dev5)
  • v0.10.0-dev5(Oct 14, 2021)

    • Added: length property to PageStack to find out how many pages the stack will generate.

    • Added: PageStackNavigator.builder constructor for advanced scenarios to filter which pages are shown in the navigator.

    • Fixed: an issue with getting RouteData.of(context) in some advanced circumstances.

    • Breaking change: renamed and refactored some core Routemaster objects. Unlikely to affect anyone unless you're making custom stateful pages.

    Source code(tar.gz)
    Source code(zip)
  • v0.10.0-dev4(Oct 7, 2021)

  • v0.10.0-dev3(Oct 7, 2021)

    Important: this release has some major breaking changes with how Routemaster interacts with the system back button on Android and web.

    • Minimum supported Flutter version is now 2.5.0.

    • Breaking change: by default, the Android system back button now navigates backwards chronologically, instead of just popping the navigation stack.

    • Breaking change: by default, tabs no longer add an entry to the web history stack. This means the browser back button will not navigate between tabs. To use the previous behavior, specify backBehavior: TabBackBehavior.history in the tab page's constructor.

    • Added: history property on Routemaster for chronological history navigation, for example Routemaster.of(context).history.back().

    • Added: popUntil to pop multiple times with a predicate.

    • Fixed: when navigating to a relative route, use the current context's path as the base, instead of the router's current path.

    Source code(tar.gz)
    Source code(zip)
  • v0.10.0-dev2(Aug 1, 2021)

    • Added: TransitionPage and TransitionBuilderPage to make it much easier to customize page push and pop animations.

    • Added: private routes - route segments that start with an underscore are not shown to the user. For example /sign-up/_stepTwo will be displayed as /sign-up in the address bar, and the user can not navigate to it by URL.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.5(Jul 11, 2021)

  • v0.9.4(Jun 17, 2021)

    • Fixed: an issue where pages were incorrectly rebuilding, causing state such as the active tab to reset
    • Fixed: you can now use the ternary operator in page builders without having to do extra casts
    Source code(tar.gz)
    Source code(zip)
  • v0.9.3(Jun 1, 2021)

  • v0.9.2(May 31, 2021)

  • v0.9.1(May 31, 2021)

  • v0.9.0(May 27, 2021)

    • Breaking change: PageStackNavigator no longer automatically provides a HeroController - to use heroes, wrap the navigator in a HeroControllerScope
    • Breaking change: refactored PageWrapper and StatefulPage (this is unlikely to affect you)
    • Added a new property to get the current route: Routemaster.of(context).currentRoute
    • Added documentation to all classes, properties and methods
    • Fixed: RouteData.of(context) sometimes throwing when navigating away from a page
    • Fixed: issue with rebuilding routes when RoutemasterDelegate is recreated
    Source code(tar.gz)
    Source code(zip)
  • v0.9.0-dev2(May 17, 2021)

    • Breaking change: refactored PageWrapper and StatefulPage (this is unlikely to affect you)
    • Added documentation to all classes, properties and methods
    Source code(tar.gz)
    Source code(zip)
  • v0.9.0-dev1(May 17, 2021)

  • v0.8.1(May 17, 2021)

  • v0.8.0(May 15, 2021)

    0.8.0

    • Breaking change: Guard properties have been renamed: validate is now canNavigate and onValidationFailed is now onNavigationFailed
    • Breaking change: removed abstract RouteConfig class; to create custom routing maps, inherit from RouteMap
    • Deprecation: StackNavigator has been renamed PageStackNavigator
    • Added NotFound return page type
    • Added ability to customise the top-level navigator with RoutemasterDelegate.builder
    • Added ability to use tabs with a custom page type
    • Fixed replace() not working with hashes on web
    • Fixed path URL strategy not working when it's set outside Routemaster
    • Fixed tabs creating a redirect loop on web
    • Note: Use of Guard is no longer recommended - use standard if statements and NotFound or Redirect
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Apr 24, 2021)

    • Added support for RoutemasterObserver in RoutemasterDelegate
    • Added support for NavigatorObserver in StackNavigator
    • Renamed tabController to controller
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Apr 4, 2021)

Fluro is a Flutter routing library that adds flexible routing options like wildcards, named parameters and clear route definitions.

English | Português The brightest, hippest, coolest router for Flutter. Features Simple route navigation Function handlers (map to a function instead

Luke Pighetti 3.5k Jan 4, 2023
Simple but powerfull Flutter navigation with riverpod and Navigator 2.0

Riverpod navigation If you are interested in the motivation why the package was created and a detailed description of what problems it solves, read th

pavelpz 20 Dec 13, 2022
Flutter Navigation Best Practices including adapting navigation to platform and branding techniques for navigation surfaces.

Flutter Navigation Best Practices including adapting navigation to platform and branding techniques for navigation surfaces.

Fred Grott 5 Aug 22, 2022
Flutter Flows made easy! A Flutter package which simplifies navigation flows with a flexible, declarative API.

Flutter Flows made easy! Usage Define a Flow State The flow state will be the state which drives the flow. Each time this state changes, a new navigat

Felix Angelov 337 Dec 31, 2022
A Flutter package for easy implementation of curved navigation bar

curved_navigation_bar pub package A Flutter package for easy implementation of curved navigation bar. Add dependency dependencies: curved_navigation

null 556 Dec 9, 2022
Fast code and awesome design-ui for flutter navigation bar

Flutter-awesome-bottom-navigation-bar ??‍?? Fast code and awesome design-ui for flutter navigation bar ?? Getting Started # First you need to add flas

Hmida 20 Nov 22, 2022
Transparent Android system navigation bar with Flutter and FlexColorScheme package.

Sysnavbar with FlexColorScheme Transparent Android system navigation bar with Flutter and FlexColorScheme. FlexColorScheme V4 Notice If you are using

Rydmike 12 Oct 21, 2022
A Custom Extended Scaffold with Expandable and Floating Navigation Bar

Custom Extended Scaffold Custom Flutter widgets that makes Bottom Navigation Floating and can be expanded with much cleaner a

Ketan Choyal 139 Dec 10, 2022
Elegant abstraction for complete deep linking navigation in Flutter

Flutter Deep Link Navigation Provides an elegant abstraction for complete deep linking navigation in Flutter. This package only provides deep linking

Dennis Krasnov 64 Dec 27, 2022
A Flutter implementation of a customizable navigation bar with animations.

A heavily customizable bottom navigation bar with some animation modifiers.

null 1 Jun 17, 2022
flutter bottom navigation bat project

bottom_navigation A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you starte

Danushan Ravendran 3 Sep 23, 2021
Custom Bottom navigation bar on Flutter.

Intro Custom Bottom navigation bar on Flutter. The updated one Support : Null safety & Support 9 items on Tabs & Some Color, Size, Effects and font cu

Ihab Zaidi 2 Oct 8, 2021
A flutter navigation package

Create By Me(Agalaba Ifeanyi Precious) go Navigate Navigate Like a pro from one Screen to another Using go navigate. go_Navigate provide you the abili

Agalaba Ifeanyi Precious 2 Oct 11, 2021
Flutter Material Design Navigation Drawer Menu

navigation_drawer_menu Flutter Material Design Navigation Drawer Menu Navigation drawer is a common UI pattern for adaptive menus. The Material Design

Christian Findlay 9 Dec 12, 2022
A Flutter package for easily implementing Material Design navigation transitions.

Morpheus A Flutter package for easily implementing Material Design navigation transitions. Examples Parent-child transition You can use MorpheusPageRo

Sander R. D. Larsen 186 Jan 7, 2023
Customized 🚀 Bottom Navigation Bar Using Flutter 🐦

Customized ?? Bottom Navigation Bar Using Flutter ??

AmirHossein Bayat 3 Dec 7, 2022
Flutter custom BottomBar Navigation Widget

bottom_bar_with_sheet ?? Non-standard way to use more space of screens in your application ?? ?? Custom bottom Sheet under Bottom Navigation Bar ?? ??

Stanislav Ilin 305 Dec 23, 2022
Persistent Bottom Navigation Bar

Persistent Bottom Navigation Bar A persistent/static bottom navigation bar for Flutter. NOTE: Those migrating from pre 2.0.0 version should check the

Bilal Shahid 421 Dec 20, 2022
A bottom navigation bar that you can customize with the options you need, without any limits.

Bottom Personalized Dot Bar A bottom navigation bar that you can customize with the options you need, without any limits. You can also customize the a

null 103 Oct 20, 2022