go_router_back_handler 1.0.2
go_router_back_handler: ^1.0.2 copied to clipboard
A robust back button handler for GoRouter that works on all routes including root routes. Solves the PopScope limitation with native Android integration.
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:go_router_back_handler/go_router_back_handler.dart';
void main() {
runApp(const MyApp());
}
final rootNavigatorKey = GlobalKey<NavigatorState>();
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
// Initialize the back button handler
GoRouterBackHandler.initialize(
navigatorKey: rootNavigatorKey,
routeHierarchy: {
// Authentication flow
'/login/otp': '/login',
'/register/step2': '/register/step1',
'/register/step3': '/register/step2',
// App navigation
'/profile': '/home',
'/settings': '/home',
'/details': '/list',
// Booking flow example
'/checkout': '/cart',
'/payment': '/checkout',
'/confirmation': '/payment',
},
rootRoutes: ['/', '/login', '/home'],
moduleHomes: {
'/home': '/',
'/list': '/home',
},
debugMode: true, // Enable debug logging
);
}
@override
void dispose() {
GoRouterBackHandler.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'GoRouter Back Handler Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
routerConfig: GoRouter(
navigatorKey: rootNavigatorKey,
initialLocation: '/',
routes: [
GoRoute(
path: '/',
builder: (context, state) => const SplashScreen(),
),
GoRoute(
path: '/login',
builder: (context, state) => const LoginScreen(),
),
GoRoute(
path: '/login/otp',
builder: (context, state) => const OtpScreen(),
),
GoRoute(
path: '/register/step1',
builder: (context, state) => const RegisterStep1Screen(),
),
GoRoute(
path: '/register/step2',
builder: (context, state) => const RegisterStep2Screen(),
),
GoRoute(
path: '/register/step3',
builder: (context, state) => const RegisterStep3Screen(),
),
GoRoute(
path: '/home',
builder: (context, state) => const HomeScreen(),
),
GoRoute(
path: '/profile',
builder: (context, state) => const ProfileScreen(),
),
GoRoute(
path: '/settings',
builder: (context, state) => const SettingsScreen(),
),
GoRoute(
path: '/list',
builder: (context, state) => const ListScreen(),
),
GoRoute(
path: '/details',
builder: (context, state) => const DetailsScreen(),
),
],
),
);
}
}
// Example Screens
class SplashScreen extends StatelessWidget {
const SplashScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.flutter_dash, size: 100, color: Colors.blue),
const SizedBox(height: 24),
const Text(
'GoRouter Back Handler',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 48),
ElevatedButton(
onPressed: () => context.go('/login'),
child: const Text('Get Started'),
),
],
),
),
);
}
}
class LoginScreen extends StatelessWidget {
const LoginScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Login')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Login Screen (Root Route)'),
const SizedBox(height: 16),
const Text('Press back to see exit confirmation'),
const SizedBox(height: 32),
ElevatedButton(
onPressed: () => context.go('/login/otp'),
child: const Text('Go to OTP'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => context.go('/register/step1'),
child: const Text('Register'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => context.go('/home'),
child: const Text('Skip to Home'),
),
],
),
),
);
}
}
class OtpScreen extends StatelessWidget {
const OtpScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('OTP Verification')),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('OTP Screen'),
SizedBox(height: 16),
Text('Press back to go to Login'),
],
),
),
);
}
}
class RegisterStep1Screen extends StatelessWidget {
const RegisterStep1Screen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Register - Step 1')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Registration Step 1'),
const SizedBox(height: 32),
ElevatedButton(
onPressed: () => context.go('/register/step2'),
child: const Text('Next'),
),
],
),
),
);
}
}
class RegisterStep2Screen extends StatelessWidget {
const RegisterStep2Screen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Register - Step 2')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Registration Step 2'),
const SizedBox(height: 16),
const Text('Press back to go to Step 1'),
const SizedBox(height: 32),
ElevatedButton(
onPressed: () => context.go('/register/step3'),
child: const Text('Next'),
),
],
),
),
);
}
}
class RegisterStep3Screen extends StatelessWidget {
const RegisterStep3Screen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Register - Step 3')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Registration Step 3'),
const SizedBox(height: 16),
const Text('Press back to go to Step 2'),
const SizedBox(height: 32),
ElevatedButton(
onPressed: () => context.go('/home'),
child: const Text('Complete'),
),
],
),
),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Home')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Home Screen (Root Route)'),
const SizedBox(height: 16),
const Text('Press back to see exit confirmation'),
const SizedBox(height: 32),
ElevatedButton(
onPressed: () => context.go('/profile'),
child: const Text('Profile'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => context.go('/settings'),
child: const Text('Settings'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => context.go('/list'),
child: const Text('List'),
),
],
),
),
);
}
}
class ProfileScreen extends StatelessWidget {
const ProfileScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Profile')),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Profile Screen'),
SizedBox(height: 16),
Text('Press back to go to Home'),
],
),
),
);
}
}
class SettingsScreen extends StatelessWidget {
const SettingsScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Settings')),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Settings Screen'),
SizedBox(height: 16),
Text('Press back to go to Home'),
],
),
),
);
}
}
class ListScreen extends StatelessWidget {
const ListScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('List')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('List Screen'),
const SizedBox(height: 16),
const Text('Press back to go to Home'),
const SizedBox(height: 32),
ElevatedButton(
onPressed: () => context.go('/details'),
child: const Text('View Details'),
),
],
),
),
);
}
}
class DetailsScreen extends StatelessWidget {
const DetailsScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Details')),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Details Screen'),
SizedBox(height: 16),
Text('Press back to go to List'),
],
),
),
);
}
}