go_router_back_handler 1.0.2 copy "go_router_back_handler: ^1.0.2" to clipboard
go_router_back_handler: ^1.0.2 copied to clipboard

PlatformAndroid

A robust back button handler for GoRouter that works on all routes including root routes. Solves the PopScope limitation with native Android integration.

example/lib/main.dart

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'),
          ],
        ),
      ),
    );
  }
}
1
likes
160
points
126
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

A robust back button handler for GoRouter that works on all routes including root routes. Solves the PopScope limitation with native Android integration.

Repository (GitHub)
View/report issues
Contributing

License

MIT (license)

Dependencies

flutter, go_router

More

Packages that depend on go_router_back_handler

Packages that implement go_router_back_handler