Easy page navigation and management in Flutter apps.

Overview

sailor

anchor_image

License: MIT pub_package

A Flutter package for easy navigation management.

Warning: Package is still under development, there might be breaking changes in future.

Index

Setup and Usage

  1. Create an instance of Sailor and add routes.
// Routes class is created by you.
class Routes {
  static final sailor = Sailor();

  static void createRoutes() {
    sailor.addRoute(SailorRoute(
        name: "/secondPage",
        builder: (context, args, params) {
          return SecondPage();
        },
      ));
  }
}
  1. Register the routes in onGenerateRoute using the generate function of Sailor and also Sailor's navigatorKey.
class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Sailor Example',
      home: Home(),
      navigatorKey: Routes.sailor.navigatorKey,  // important
      onGenerateRoute: Routes.sailor.generator(),  // important
    );
  }
}
  1. Make sure to create routes before starting the application.
void main() async {
  Routes.createRoutes();
  runApp(App());
}
  1. Use the instance of Sailor to navigate.
Routes.sailor.navigate("/secondPage");
  • TIP: Sailor is a callable class, so you can omit navigate and directly call the method.
Routes.sailor("/secondPage");

Passing Parameters

Sailor allows you to pass parameters to the page that you are navigating to.

  • Before passing the parameter itself, you need to declare it while declaring your route. Let's declare a parameter named id that has a default value of 1234.
sailor.addRoutes([
  SailorRoute(
    name: "/secondPage",
    builder: (context, args, params) => SecondPage(),
    params: [
      SailorParam<int>(
        name: 'id',
        defaultValue: 1234,
      ),
    ],
  ),
);
  • Pass the actual parameter when navigating to the new route.
Routes.sailor.navigate<bool>("/secondPage", params: {
  'id': 4321,
});
  • Parameters can be retrieved from two places, first, the route builder and second, the opened page itself.

Route Builder:

sailor.addRoutes([
  SailorRoute(
    name: "/secondPage",
    builder: (context, args, params) {
      // Getting a param
      final id = params.param<int>('id');
      return SecondPage();
    },
    params: [
      SailorParam(
        name: 'id',
        defaultValue: 1234,
      ),
    ],
  ),
);

Opened page:

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final id = Sailor.param<int>(context, 'id');

    ...

  }
}

Make sure to specify the type of paramter when declaring SailorParam<T>. This type is used to make sure when the route is being opened, it is passed the correct param type. Right now Sailor logs a warning if the type of declared and passed param is not same. In future version this might throw an error.

Passing Arguments

Sailor allows you to pass arguments to the page that you are navigating to.

  • Create a class that extends from BaseArguments.
class SecondPageArgs extends BaseArguments {
  final String text;

  SecondPageArgs(this.text);
}
  • When calling the navigate method pass these arguments.
final response = Routes.sailor.navigate(
  "/secondPage",
  args: SecondPageArgs('Hey there'),
);
  • When in the SecondPage, use Sailor.args to get the passed arguments.
class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final args = Sailor.args<SecondPageArgs>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Compass Example'),
      ),
      body: Center(
        child: Text(args.text),
      ),
    );
  }
}

Route Guards (Experimental)

Routes can be protected from being opened when navigate is called using route guard.

A route guard can be added when declaring a SailorRoute.

sailor.addRoutes([
  SailorRoute(
    name: "/secondPage",
    builder: (context, args, params) => SecondPage(),
    routeGuards: [
      SailorRouteGuard.simple((context, args, params) async {
        // Can open logic goes here.
        if (sharedPreferences.getToken() != null) {
          return true;
        }
        return false;
      }),
    ],
  ),
);

routeGuards takes an array of SailorRouteGuard.

There are two ways to create a route guard:

  • Using SailorRouteGuard.simple, as shown above.
SailorRouteGuard.simple((context, args, params) async {
  // Can open logic goes here.
  if (sharedPreferences.getToken() != null) {
    return true;
  }
  return false;
});
  • Extending SailorRouteGuard class.
class CustomRouteGuard extends SailorRouteGuard {
  @override
  Future<bool> canOpen(
    BuildContext context,
    BaseArguments args,
    ParamMap paramMap,
  ) async {
    return false;
  }
}

The result from each route guard is Future<bool>. If the value returned by each route is true the route is accepted and opened, anything else will result in route being rejected and not being opened.

Transitions

Sailor has inbuilt support for page transitions. A transition is specified using SailorTransition.

Transition can be specified at 3 levels (ordered in priority from highest to lowest):

  • When Navigating (using Sailor.navigate).
  • While adding routes (SailorRoute).
  • Global transitions (SailorOptions).

When navigating

Specify which transitions to use when calling the navigate method.

Routes.sailor.navigate(
  "/secondPage",
  transitions: [SailorTransition.fade_in],
);

More than one transition can be provided when navigating a single route. These transitions are composed on top of each other, so in some cases changing the order will change the animation.

Routes.sailor.navigate(
  "/secondPage",
  transitions: [
    SailorTransition.fade_in,
    SailorTransition.slide_from_right,
  ],
  transitionDuration: Duration(milliseconds: 500),
  transitionCurve: Curves.bounceOut,
);

Duration and Curve can be provided using transitionDuration and transitionCurve respectively.

Routes.sailor.navigate(
  "/secondPage",
  transitions: [
    SailorTransition.fade_in,
    SailorTransition.slide_from_right,
  ],
  transitionDuration: Duration(milliseconds: 500),
  transitionCurve: Curves.bounceOut,
);

In the above example the page will slide in from right with a fade in animation. You can specify as many transitions as you want.

When adding routes

You can specify the default transition for a route, so you don't have to specify it again and again when navigating.

sailor.addRoute(SailorRoute(
  name: "/secondPage",
  defaultTransitions: [
    SailorTransition.slide_from_bottom,
    SailorTransition.zoom_in,
  ],
  defaultTransitionCurve: Curves.decelerate,
  defaultTransitionDuration: Duration(milliseconds: 500),
  builder: (context, args) => SecondPage(),
));

Priority: Transitions provided in Sailor.navigate while navigating to this route, will override these transitions.

Global transitions

You can specify default transition to be used for all routes in Sailor.

SailorOptions(
  defaultTransitions: [
    SailorTransition.slide_from_bottom,
    SailorTransition.zoom_in,
  ],
  defaultTransitionCurve: Curves.decelerate,
  defaultTransitionDuration: Duration(milliseconds: 500),
)

Priority: Transitions provided while adding a route or when navigating using navigate, will override these transitions.

Custom Transitions

Although sailor provides you with a number of out of the box transitions, you can still provide your own custom transitions.

  • To create a custom transition, extend the class CustomSailorTransition and implement buildTransition method.
class MyCustomTransition extends CustomSailorTransition {
  @override
  Widget buildTransition(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    Widget child,
  ) {
    return FadeTransition(
      opacity: animation,
      child: child,
    );
  }
}

This transition can now be provided at 3 places:

  • While calling navigate.
Routes.sailor.navigate<bool>(
  "/secondPage",
  customTransition: MyCustomTransition(),
);
  • When declaring a SailorRoute.
SailorRoute(
  name: "/secondPage",
  builder: (context, args, params) => SecondPage(),
  customTransition: MyCustomTransition(),
),
  • In SailorOptions:
static final sailor = Sailor(
  options: SailorOptions(
    customTransition: MyCustomTransition(),
  ),
);

Custom Transition Priority

NOTE: Custom transitions have the highest priority, if you provide a custom transition, they will be used over Sailor's inbuilt transitions.

The same priority rules apply to custom transitions as inbuilt sailor transitions, with the added rule that at any step if both transitions are provided (i.e. Sailor's inbuilt transitions and a CustomSailorTransition), the custom transition will be used over inbuilt one.

For example, in the below code, MyCustomTransition will be used instead of SailorTransition.slide_from_top.

Routes.sailor.navigate<bool>(
  "/secondPage",
  transitions: [
    SailorTransition.slide_from_top,
  ],
  customTransition: MyCustomTransition(),
);

Pushing Multiple Routes

Sailor allows you to push multiple pages at the same time and get collected response from all.

final responses = await Routes.sailor.navigateMultiple(context, [
  RouteArgsPair("/secondPage", SecondPageArgs("Multi Page!")),
  RouteArgsPair("/thirdPage", ThirdPageArgs(10)),
]);

print("Second Page Response ${responses[0]}");
print("Third Page Response ${responses[1]}");

Log Navigation

Use SailorLoggingObserver to log the push/pop navigation inside the application. Add the SailorLoggingObserver to the navigatorObservers list inside your MaterialApp.

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Compass Example',
      home: Home(),
      onGenerateRoute: Routes.sailor.generator(),
      navigatorObservers: [
        SailorLoggingObserver(),
      ],
    );
  }
}

Once added, start navigating in your app and check the logs. You will see something like this.

flutter: [Sailor] Route Pushed: (Pushed Route='/', Previous Route='null', New Route Args=null, Previous Route Args=null)
flutter: [Sailor] Route Pushed: (Pushed Route='/secondPage', Previous Route='/', New Route Args=Instance of 'SecondPageArgs', Previous Route Args=null)
flutter: [Sailor] Route Popped: (New Route='/', Popped Route='/secondPage', New Route Args=null, Previous Route Args=Instance of 'SecondPageArgs')

Support

If you face any issue or want a new feature to be added to the package, please create an issue. I will be more than happy to resolve your queries.

Comments
  • Package broken on Master

    Package broken on Master

    I updated my Flutter SDK to

    Flutter 1.15.4-pre.274 • channel master • https://github.com/flutter/flutter.git
    Framework • revision cbbb7ec5a7 (14 hours ago) • 2020-03-04 12:40:15 -0800
    Engine • revision 90bd6f8148
    Tools • Dart 2.8.0 (build 2.8.0-dev.11.0 5701c4fd3b)
    

    Then i got this when trying to run my project

    Compiler message:
    [   +2 ms] ../../../Development/flutter/.pub-cache/hosted/pub.dartlang.org/sailor-0.6.0/lib/src/sailor.dart:509:9: Error: No named parameter with the name
    'isInitialRoute'.
    [        ]         isInitialRoute: settings.isInitialRoute,
    [        ]         ^^^^^^^^^^^^^^
    [        ] ../../../Development/flutter/packages/flutter/lib/src/widgets/navigator.dart:419:9: Context: Found this candidate, but the arguments don't match.
    [        ]   const RouteSettings({
    [        ]         ^^^^^^^^^^^^^
    [+2956 ms] 
                        Compiler message:
    [        ] ../../../Development/flutter/.pub-cache/hosted/pub.dartlang.org/sailor-0.6.0/lib/src/sailor.dart:509:9: Error: No named parameter with the name
    'isInitialRoute'.
    [        ]         isInitialRoute: settings.isInitialRoute,
    [        ]         ^^^^^^^^^^^^^^
    [        ] ../../../Development/flutter/packages/flutter/lib/src/widgets/navigator.dart:419:9: Context: Found this candidate, but the arguments don't match.
    [        ]   const RouteSettings({
    [        ]         ^^^^^^^^^^^^^
    [+4452 ms] Persisting file store
    [   +9 ms] Done persisting file store
    [   +1 ms] Target kernel_snapshot failed: Exception: Errors during snapshot creation: null
    [        ] Failed to build bundle.
    [        ] Error launching application on iPhone 11 Pro Max.
    [  +14 ms] "flutter run" took 14,128ms.
    
    #0      throwToolExit (package:flutter_tools/src/base/common.dart:14:3)
    #1      RunCommand.runCommand (package:flutter_tools/src/commands/run.dart:568:7)
    <asynchronous suspension>
    #2      FlutterCommand.verifyThenRunCommand (package:flutter_tools/src/runner/flutter_command.dart:711:18)
    #3      _rootRunUnary (dart:async/zone.dart:1134:38)
    #4      _CustomZone.runUnary (dart:async/zone.dart:1031:19)
    #5      _FutureListener.handleValue (dart:async/future_impl.dart:140:18)
    #6      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
    #7      Future._propagateToListeners (dart:async/future_impl.dart:711:32)
    #8      Future._completeWithValue (dart:async/future_impl.dart:526:5)
    #9      _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:34:15)
    #10     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:293:13)
    #11     RunCommand.usageValues (package:flutter_tools/src/commands/run.dart)
    #12     _rootRunUnary (dart:async/zone.dart:1134:38)
    #13     _CustomZone.runUnary (dart:async/zone.dart:1031:19)
    #14     _FutureListener.handleValue (dart:async/future_impl.dart:140:18)
    #15     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
    #16     Future._propagateToListeners (dart:async/future_impl.dart:711:32)
    #17     Future._completeWithValue (dart:async/future_impl.dart:526:5)
    #18     Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:556:7)
    #19     _rootRun (dart:async/zone.dart:1126:13)
    #20     _CustomZone.run (dart:async/zone.dart:1023:19)
    #21     _CustomZone.runGuarded (dart:async/zone.dart:925:7)
    #22     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:965:23)
    #23     _microtaskLoop (dart:async/schedule_microtask.dart:43:21)
    #24     _startMicrotaskLoop (dart:async/schedule_microtask.dart:52:5)
    #25     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13)
    #26     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:169:5)
    
    opened by iamEtornam 15
  • Feature/route guard redirect

    Feature/route guard redirect

    Implementation for redirect feature mention at https://github.com/gurleensethi/sailor/issues/28

    This PR included commits from these PRs:

    • https://github.com/gurleensethi/sailor/pull/27
    • https://github.com/gurleensethi/sailor/pull/30

    Example

    SailorRoute(
      name: 'user_info',
      builder: (context, args, params) => UserInfoPage(),
      routeGuards: [
        SailorRouteGuard.simple((context, args, params) async {
          if (userBloc.isLoggedIn) {
            return true;
          } else {
            // Redirect to login page
            return RouteArgsPair('/login');
          }
        }),
      ],
    ),
    
    opened by CasperPas 2
  • Example rising analysis warning: avoid_classes_with_only_static_members

    Example rising analysis warning: avoid_classes_with_only_static_members

    Is it possible to actually have the createRoutes function not as static method? If I do this, I just have to change in my main.dart to call Router().createRoutes(); instead of Router.createRoutes(), and it seems it's still working fine. Not sure i understand the implications.

    opened by talamaska 2
  • Error in 0.7.0

    Error in 0.7.0

    Compiler message: ../../dev-tools/flutter/.pub-cache/hosted/pub.dartlang.org/sailor-0.7.0/lib/src/sailor.dart:429:43: Error: Can't return a value from a void function. return this.navigatorKey.currentState.pop(result); ^

    Build fails.

    opened by jonny7737 1
  • Sailor not working at all

    Sailor not working at all

    Good day, i am trying out sailor for the first time, and i am not finding it funny. i have just setup a new application and trying out sailor but it keeps giving this error,

    Compiler message: /C:/tools/flutter/.pub-cache/hosted/pub.dartlang.org/sailor-0.7.0/lib/src/sailor.dart:429:43: Error: Can't return a value from a void function. return this.navigatorKey.currentState.pop(result); ^ Target kernel_snapshot failed: Exception: Errors during snapshot creation: null build failed.

    Please here is the code block for you perusual.

    import 'package:flutter/material.dart';
    import 'package:sailor/sailor.dart';
    
    void main() {
      Routes.createRoutes();
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
          onGenerateRoute: Routes.sailor.generator(),
          navigatorKey: Routes.sailor.navigatorKey,
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.display1,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }
    
    class SecondPage extends StatelessWidget {
      const SecondPage({Key key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Text("This is the second page"),
        );
      }
    }
    
    class ThirdPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Text("This is the third page"),
        );
      }
    }
    
    class Routes {
      static final sailor = Sailor();
    
      static void createRoutes() {
        sailor.addRoutes(
          [
            SailorRoute(
              name: "/first-page",
              builder: (context, args, param) => MyHomePage(),
            ),
            SailorRoute(
              name: "/second-page",
              builder: (context, args, param) => SecondPage(),
            ),
            SailorRoute(
              name: "/third-page",
              builder: (context, args, param) => ThirdPage(),
            ),
          ],
        );
      }
    }
    

    Thanks. I love the syntax of sailor but i am unable to use it #26

    opened by peterson-umoke 1
  • Allow setting custom navigation key

    Allow setting custom navigation key

    It would be great if we could set a custom GlobalKey<NavigatorState> navigatorKey which defaults to the existing one if not provided. This would make it easier to integrate Sailor with other libraries that also rely on the navigator key.

    feature 
    opened by kuhnroyal 1
  • How can I use param data in initState in new page?

    How can I use param data in initState in new page?

    Hi,

    I need to send from main.dart the "_startDate" and "_endDate" to new page. In new page in initState I need to use these values before building a new page. If I use param the data was empty.

    What is the best way to use the values in new page initState? Any example much appreciated.

    opened by NTMS2017 0
  • How can I retrieve the param values in opened page in initState?

    How can I retrieve the param values in opened page in initState?

    In my route:

            SailorRoute(
              name: "/ACCOUNT_DETAILS",
              builder: (context, args, params) => AccountDetails(),
              customTransition: MyCustomTransition(),
              defaultTransitions: [
                SailorTransition.slide_from_bottom,
                SailorTransition.zoom_in,
              ],
              params: [
                SailorParam<String>(
                  name: 'userAccountNo',
                  defaultValue: "...",
                ),
                SailorParam<String>(
                  name: 'userAccountType',
                  defaultValue: "...",
                ),
              ],
            ),
    

    Passing the actual parameter when navigating to the new route:

      Future<void> _navigationToAccountsDetailPage() async {
        await Future.delayed(Duration(milliseconds: 400), () async {
          Routes.sailor.pop(true);
          await Routes.sailor.navigate("/ACCOUNT_DETAILS",
              params: {"userAccountNo": _userAccountNo, "userAccountType": _userAccountType});
        });
      }
    

    This also printed empty

      @override
      void didChangeDependencies() {
        super.didChangeDependencies();
    
        final _userAccountNo = Sailor.param<String>(context, 'userAccountNo');
        final _userAccountType = Sailor.param<String>(context, 'userAccountType');
    
        print("_userAccountNo: $_userAccountNo");
        print("_userAccountType: $_userAccountType");
      }
    

    But how can I retrieve the values in opened (AccountsDetailPage) page in initState??

    opened by NTMS2017 0
  • How to return login page after logout

    How to return login page after logout

    Hi,

    I have login page and after user successfully logged in it redirects to home page. User Interaction is 10 min. Meaning if user not interact with app 10 min. it redirects to login page.

    But after redirects the login page the login page textfield and login button is not working. Any idea?

    PS: Also I want to remove all other pages after login. I want to remove every page from stack from home page and home page onward. As shown below when app try to redirects from logout anything in stack from Home Page to Payment Page must be remove.

    - Main Screen
    - Login Page
    - Home Page
    - Account Page
         - Account Summary
         - Account Edit
         - Account View
    - Card Page
         - Card Summary
         - Card Edit
         - Card View
    - Payment Page
         - Payment Summary
         - Make Payment
    - Logout Page
    

    My Routes Class:

    class Routes {
      static final sailor = Sailor(
        options: SailorOptions(
          handleNameNotFoundUI: true,
          isLoggingEnabled: true,
          customTransition: MyCustomTransition(),
          defaultTransitions: [
            SailorTransition.slide_from_bottom,
            SailorTransition.zoom_in,
          ],
          defaultTransitionCurve: Curves.decelerate,
          defaultTransitionDuration: Duration(milliseconds: 500),
        ),
      );
    
      /// ROUTES
      static void createRoutes() {
        sailor.addRoutes(
          [
            SailorRoute(
              name: "/LOGIN_PAGE",
              builder: (context, args, params) => LoginPage(),
            ),
            SailorRoute(
              name: "/HOME_PAGE",
              builder: (context, args, params) => HomePage(),
            ),
    
           .....
           .....
           .....
           .....
           .....
    
    

    User Login Button:

     InkWell(
                splashColor: yellowColor,
                onTap: () {
                  Routes.sailor.navigate("/HOME_PAGE"); 
                },
    

    My Logout function:

      Future<void> _navigationToLoginPage() async {
        await Future.delayed(Duration.zero, () async {
          Routes.sailor.pop(true);
          await Routes.sailor.navigate("/LOGIN_PAGE");
        });
      }
    
    opened by NTMS2017 0
  • Replacing a screen

    Replacing a screen

    Hi there. I started using this package like a week ago, as I got it as a suggestion. And all I can say is that I love it. I enjoy using it given the simplicity of the package.

    However when making my current app, I've gotten into a scenario where I need to replace my current screen (moving from a login screen to another screen) and disable returning back unless the user chooses to (i.e.: log out).

    Will there be any possibility of making a replace method in the future? Are there any hacky ways of doing this now?

    Edit: I am stupid. Should have researched more before posting here. Haven't seen 'navigationType' parameter in the navigate method.

    opened by dacher996 0
  • [Docs] Difference to Navigator/Router

    [Docs] Difference to Navigator/Router

    Maybe it's just me, but after 2 mins of reading the documentation I didn't see the main benefit of this package compared to Navigator or Router already integrated in flutter. You really should stress this out in the documentation first (what's the problem you are trying to solve and who is this package for).

    Good luck.

    opened by Babwenbiber 0
  • Convenient way for multiple navigation stacks

    Convenient way for multiple navigation stacks

    Is there any convenient way to have multiple navigation stacks? This would really come in hanndy for applications using a bottom navigation bar or something similar. The expected behaviour would be similar to the YouTube app.

    opened by DennisSchm 0
  • Is there any way to access arguments from URL in Flutter Web?

    Is there any way to access arguments from URL in Flutter Web?

    I am currently building an application which contains a list of items.

    I noticed that Sailor does add the route name to the URL as you would expect from a normal web app.

    I also do know we can programmatically pass arguments and params to the pages when navigating to the route.

    My question is, is there any way to get the arguments passed in the URL with Sailor?

    That is, if we have http://localhost:62656/#/book?id=1

    Can I get the id from the URL as an argument for the route?

    opened by tapizquent 0
Releases(v0.7.1)
  • v0.7.1(Apr 11, 2020)

  • v0.7.0(Apr 7, 2020)

  • v0.6.0(Nov 15, 2019)

    • Route Guards: Prevent routes from being opened based on a condition.
    • More type checking for SailorParams: SailorParams<T> now accept a generic type T, of the type of paramter that is required to be passed. When opening a route, runtimeType of the passed value is compred to the T passed when declaring SailorParam<T>.
    • Provider navigationKey: An external navigatorKey can be provided to sailor using SailorOptions.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Sep 20, 2019)

Owner
Gurleen Sethi
Software Engineer
Gurleen Sethi
A TabBarController that is easy to use for flutter developers. 🥰 It supports various styles of page navigation, and you can also use it to customize your favorite styles. 🍻🍻

easy_tab_controller A user-friendly TabBarController widget for flutter developer. Getting Started This project is a starting point for a Flutter plug

圆号本昊 3 May 26, 2022
Flutter Navigation - all types of navigation in flutter run main.tabBar.dart to see tabBar, and run main.dart to see the otheres

pop_up_bar A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if th

Michael Odumosu 0 Jan 1, 2022
FLUTTER API: It's powerful navigation by gestures and taps. You can scroll from left to right or tap on the navigation icons.

scroll_navigation My other APIs Video Viewer Video Editor Helpers Features Fancy animations. Customizable colors. Works with the back button. Scrollin

Luis Felipe Murguia Ramos 14 Jun 14, 2022
Smooth-Page-Indicator-Example-Flutter - A simple example about smooth page indicator in Flutter

Smooth Page Indicator Example - Flutter Screenshots ⚠️ Essential Packages smooth

AmirHossein Bayat 6 Dec 7, 2022
A package that offers various page indicators inlcuding a Flutter implementation of the Ink Page Indicator

A package that offers various page indicators inlcuding a Flutter implementation of the Ink Page Indicator. See below for more examples.

null 50 Jan 6, 2022
OnBoarding Animation provides page like animation to the onBoarding screens with the page indicator

OnBoarding Animation OnBoarding Animation provides page like animation to the onBoarding screens with the page indicator. Screenshots and Screen recor

null 13 Oct 12, 2022
Login-page-ui - An animated login page, designed with dart

Beautiful Login Page UI Design and Animation ScreenShots This is one of my best

Munem Sarker 11 Nov 22, 2022
Login-with-Register-page - A Login with Register page combined with all movable images made with Dart

Flutter login page with register page A new dart project designed for login page

Munem Sarker 3 Aug 2, 2022
Doctor Consultation App in Flutter containing splash screen on boarding screen Routing state management Dash board Bottom navigation Decorated Drawer and Doctors Screen in the last.

Online doctor Consultation App UI in Flutter Doctor Consultation App UI in Flutter Visit Website Features State Management Navigation Bar Responsive D

Habib ullah 14 Jan 1, 2023
Overlapping panels - Discord inspired navigation for Flutter apps

Overlapping Panels Add Discord-like navigation to your app. Demo project here: o

Degreat 30 Dec 23, 2022
Sūpāhīrō is a demo app for the talk/write on super charging your navigation 1.0 in flutter apps

navhero A simple experiment to give nav1.0 super powers. Named routing in Nav 1.0 could get messy, with large router files here and there. This projec

Samuel Abada 9 Dec 3, 2022
A very easy-to-use navigation tool/widget for having iOS 13 style stacks.

cupertino_stackview A very easy-to-use navigation tool/widget for having iOS 13 style stacks. It is highly recommended to read the documentation and r

AliYigitBireroglu 49 Nov 18, 2022
A rich, convenient, easy-to-use flutter page transition package

flutter_page_transition A rich, convenient, easy-to-use flutter page transition package. README in Chinese Some Demos Getting Started Add this to your

Double Han 56 Sep 27, 2022
With cupertino_setting_control you can create a settings page or a simple form very easy.

Flutter Cupertino Setting Control With cupertino_setting_control you can create a settings page or a simple form very easy. Therefore, cupertino_setti

Christoph Rothermel 7 Mar 28, 2022
Shopify Tag and Product Management App using Flutter and Riverpod State Management

Myshopify App A Simple Flutter Application project to get List of Tags, Products and Product Details from shopify https://shopicruit.myshopify.com/adm

Idowu Tomiwa 5 Nov 12, 2022
Flutter makes it easy and fast to build beautiful apps for mobile and beyond

Flutter is Google's SDK for crafting beautiful, fast user experiences for mobile, web, and desktop from a single codebase. Flutter works with existing

Flutter 148.2k Jan 8, 2023
Github-apps-flutter - Github Apps Build Using bloc 8.0 and Github API

Github_apps Inspiration This app is made to build using bloc 8.0 and github API.

Irvan Lutfi Gunawan 18 Apr 14, 2022
⚡FQuery is a powerful async state management solution for flutter. It caches, updates and fully manages asynchronous data in your flutter apps.

⚡ FQuery is a powerful async state management solution for flutter. It caches, updates and fully manages asynchronous data in your flutter apps. It ca

Piyush 21 Dec 22, 2022
A light, powerful and reactive state management for Flutter Apps.

A light, powerful and reactive state management. Features ⚡️ Build for speed. ?? Reduce boilerplate code significantly. ?? Improve code readability. ?

2devs 3 Dec 15, 2022