Last updated:
0 purchases
hopper
A package for using Flutter Navigator 2.0. #
Features #
It supports deep links
It supports passing parameters to other pages associated with the path
It supports async calls like await hopNamed('/setting_page')
It supports guards
Why did I write this package? #
I had an app which I developed for a client which It used Flutter Navigator 1.0, and I needed a new package a new use case to navigate to deep links which version 1.0 does not support. Then I decided to try some package out there on pub.dev beamer which is a good package but unfortunately it did not support await beamNamed(...etc), so I opened a thread on github.com, and the author mentioned that this will be added (as for today is 06.feb.2022 when I'm mentioning it here in this readme, and maybe in the future as you are reading this, it's already added).
So I decided to create this package and to migrate my app to it, and also I was in a hurry to write this package in order to finish my tasks related to the job (mobile app for the client).
This package until version 1.0.0 was written in 2 days
Getting started #
Simple app with one home page #
Add the package into your pubspec.yaml
dependencies:
flutter:
sdk: flutter
hopper: ^1.2.0
copied to clipboard
Create your main.dart file and add the following code:
import 'package:counter/router/classes.dart';
import 'package:flutter/material.dart';
import 'package:hopper/hopper.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final routerDelegate = AppRouter();
final routeInformationParser = AppRouteInformationParser();
MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Flutter Demo',
routerDelegate: routerDelegate,
routeInformationParser: routeInformationParser,
);
}
}
copied to clipboard
Create a folder (not necessary) named router inside the lib folder and create a file named classes.dart (you can choose any name, but then you need to import it) and add the following code:
import 'package:counter/home_page.dart';
import 'package:flutter/material.dart';
import 'package:hopper/hopper.dart';
class AppRouter extends AbstractAppRouter {
final GlobalKey<NavigatorState> navigatorKey;
static const String initialRoute = '/';
AppRouter()
: navigatorKey = GlobalKey<NavigatorState>(),
super((AbstractAppRouter appRouter) => AppNavigationManager(appRouter));
}
class AppNavigationManager extends AbstractAppNavigationManager {
final AbstractAppRouter routerDelegate;
AppNavigationManager(this.routerDelegate) : super(routerDelegate);
@override
List<AppLocation> get locations => [
HomeLocation(),
];
}
class HomeLocation extends AppLocation {
static const String route = '/';
@override
List<Pattern> get pathPatterns => [route];
@override
List<AppPage> buildPages(String path, Map<String, dynamic>? params) {
return [
const AppPage(
key: ValueKey('home'),
title: 'Home',
child: HomePage(title: 'Home Page',),
),
];
}
@override
String getRoute() {
return route;
}
}
copied to clipboard
Add a home page (this ia a counter app page)
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<HomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<HomePage> {
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>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
copied to clipboard
Run the app
Guards #
The package also supports guards
class AppNavigationManager extends AbstractAppNavigationManager {
final AbstractAppRouter routerDelegate;
AppNavigationManager(this.routerDelegate) : super(routerDelegate);
@override
List<AppNavigationGuard> guards = [
AppNavigationGuard(
guardExcludePattern: r"(/project_manager_login|/technician_login|/app_settings|/device_assignment)$",
guardPattern: r"/*",
guard: (path) {
final appCubit = AppDi().appCubit();
if (appCubit.state.appToken.isEmpty &&
appCubit.state.authToken.isEmpty) {
return ProjectManagerLoginLocation();
} else if (appCubit.state.appToken.isNotEmpty &&
appCubit.state.authToken.isEmpty) {
return TechnicianLoginLocation();
} else if (appCubit.state.appToken.isEmpty &&
appCubit.state.authToken.isNotEmpty) {
return DeviceAssignmentLocation();
} else {
return null;
}
},
),
];
@override
List<AppLocation> get locations => [
ProjectManagerLoginLocation(),
DeviceAssignmentLocation(),
TechnicianLoginLocation(),
AppSettingsLocation(),
HomeLocation(),
];
}
copied to clipboard
Usage #
The package uses extension with BuildContext, see the following examples:
You can navigate to a page by using:
* context.hopNamed('/home');
* context.hopReplacementNamed('/home');
copied to clipboard
You can pass parameters associated with the path: #
* context.hopNamed('/home', {"id": 1, "name": "John"});
copied to clipboard
Return from a page #
* context.hopBack();
* context.hopBack(result); // return a result from a page
copied to clipboard
Close a dialog window or drawer #
* Navigator.of(context).pop();
copied to clipboard
You can wait for a result from a page: #
* int code = await context.hopNamed('/get_some_code');
copied to clipboard
Additional information #
Check the exmple folder for more examples.
You will find also deeplinks example that shows how to jump into the deep page and get back to previous page(s).
Contribution #
You can contribute to this package in order to make add new features, fix bugs, etc.
Note #
This package is not suitable for browser based applications (By contribution it can make it possible to use it in a browser based app).
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.