flutter-implementing-navigation-and-routing

Handles routing, navigation, and deep linking in a Flutter application. Use when moving between screens or setting up URL-based navigation.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "flutter-implementing-navigation-and-routing" with this command: npx skills add flutter/skills/flutter-skills-flutter-implementing-navigation-and-routing

Implementing Navigation and Routing in Flutter

Contents

Core Concepts

  • Routes: In Flutter, screens and pages are referred to as routes. A route is simply a widget. This is equivalent to an Activity in Android or a ViewController in iOS.
  • Navigator vs. Router:
    • Use Navigator (Imperative) for small applications without complex deep linking requirements. It manages a stack of Route objects.
    • Use Router (Declarative) for applications with advanced navigation, web URL synchronization, and specific deep linking requirements.
  • Deep Linking: Allows an app to open directly to a specific location based on a URL. Supported on iOS, Android, and Web. Web requires no additional setup.
  • Named Routes: Avoid using named routes (MaterialApp.routes and Navigator.pushNamed) for most applications. They have rigid deep linking behavior and do not support the browser forward button. Use a routing package like go_router instead.

Implementing Imperative Navigation

Use the Navigator widget to push and pop routes using platform-specific transition animations (MaterialPageRoute or CupertinoPageRoute).

Pushing and Popping

  • Navigate to a new route using Navigator.push(context, route).
  • Return to the previous route using Navigator.pop(context).
  • Use Navigator.pushReplacement() to replace the current route, or Navigator.pushAndRemoveUntil() to clear the stack based on a condition.

Passing and Returning Data

  • Sending Data: Pass data directly into the constructor of the destination widget. Alternatively, pass data via the settings: RouteSettings(arguments: data) parameter of the PageRoute and extract it using ModalRoute.of(context)!.settings.arguments.
  • Returning Data: Pass the return value to the pop method: Navigator.pop(context, resultData). Await the result on the pushing side: final result = await Navigator.push(...).

Implementing Declarative Navigation

For apps requiring deep linking, web URL support, or complex routing, implement the Router API via a declarative routing package like go_router.

  • Switch from MaterialApp to MaterialApp.router.
  • Define a router configuration that parses route paths and configures the Navigator automatically.
  • Navigate using package-specific APIs (e.g., context.go('/path')).
  • Page-backed vs. Pageless Routes: Declarative routes are page-backed (deep-linkable). Imperative pushes (e.g., dialogs, bottom sheets) are pageless. Removing a page-backed route automatically removes all subsequent pageless routes.

Implementing Nested Navigation

Implement nested navigation to manage a sub-flow of screens (e.g., a multi-step setup process or persistent bottom navigation tabs) independently from the top-level global navigator.

  • Instantiate a new Navigator widget inside the host widget.
  • Assign a GlobalKey<NavigatorState> to the nested Navigator to control it programmatically.
  • Implement the onGenerateRoute callback within the nested Navigator to resolve sub-routes.
  • Intercept hardware back button presses using PopScope to prevent the top-level navigator from popping the entire nested flow prematurely.

Workflows

Workflow: Standard Screen Transition

Copy this checklist to track progress when implementing a basic screen transition:

  • Create the destination widget (Route).
  • Define required data parameters in the destination widget's constructor.
  • Implement Navigator.push() in the source widget.
  • Wrap the destination widget in a MaterialPageRoute or CupertinoPageRoute.
  • Implement Navigator.pop() in the destination widget to return.

Workflow: Implementing Deep-Linkable Routing

Use this conditional workflow when setting up app-wide routing:

  • If the app is simple and requires no deep linking:
    • Use standard MaterialApp and Navigator.push().
  • If the app requires deep linking, web support, or complex flows:
    • Add the go_router package.
    • Change MaterialApp to MaterialApp.router.
    • Define the GoRouter configuration with all top-level routes.
    • Replace Navigator.push() with context.go() or context.push().

Workflow: Creating a Nested Navigation Flow

Run this workflow when building a multi-step sub-flow (e.g., IoT device setup):

  • Define string constants for the nested route paths.
  • Create a GlobalKey<NavigatorState> in the host widget's state.
  • Return a Navigator widget in the host's build method, passing the key.
  • Implement onGenerateRoute in the nested Navigator to map string paths to specific step widgets.
  • Wrap the host Scaffold in a PopScope to handle back-button interceptions (e.g., prompting "Are you sure you want to exit setup?").
  • Use navigatorKey.currentState!.pushNamed() to advance steps within the flow.

Examples

Example: Passing Data via Constructor (Imperative)

// 1. Define the data model
class Todo {
  final String title;
  final String description;
  const Todo(this.title, this.description);
}

// 2. Source Screen
class TodosScreen extends StatelessWidget {
  final List<Todo> todos;
  const TodosScreen({super.key, required this.todos});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Todos')),
      body: ListView.builder(
        itemCount: todos.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(todos[index].title),
            onTap: () {
              // Push and pass data via constructor
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => DetailScreen(todo: todos[index]),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

// 3. Destination Screen
class DetailScreen extends StatelessWidget {
  final Todo todo;
  const DetailScreen({super.key, required this.todo});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(todo.title)),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Text(todo.description),
      ),
    );
  }
}

Example: Nested Navigation Flow

class SetupFlow extends StatefulWidget {
  final String initialRoute;
  const SetupFlow({super.key, required this.initialRoute});

  @override
  State<SetupFlow> createState() => _SetupFlowState();
}

class _SetupFlowState extends State<SetupFlow> {
  final _navigatorKey = GlobalKey<NavigatorState>();

  void _exitSetup() => Navigator.of(context).pop();

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: (didPop, _) async {
        if (didPop) return;
        // Intercept back button to prevent accidental exit
        _exitSetup(); 
      },
      child: Scaffold(
        appBar: AppBar(title: const Text('Setup')),
        body: Navigator(
          key: _navigatorKey,
          initialRoute: widget.initialRoute,
          onGenerateRoute: _onGenerateRoute,
        ),
      ),
    );
  }

  Route<Widget> _onGenerateRoute(RouteSettings settings) {
    Widget page;
    switch (settings.name) {
      case 'step1':
        page = StepOnePage(
          onComplete: () => _navigatorKey.currentState!.pushNamed('step2'),
        );
        break;
      case 'step2':
        page = StepTwoPage(onComplete: _exitSetup);
        break;
      default:
        throw StateError('Unexpected route name: ${settings.name}!');
    }

    return MaterialPageRoute(
      builder: (context) => page,
      settings: settings,
    );
  }
}

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

flutter-layout

No summary provided by upstream source.

Repository SourceNeeds Review
1.2K-flutter
General

flutter-performance

No summary provided by upstream source.

Repository SourceNeeds Review
1.2K-flutter
General

flutter-theming

No summary provided by upstream source.

Repository SourceNeeds Review
1.1K-flutter
General

flutter-animation

No summary provided by upstream source.

Repository SourceNeeds Review
1.1K-flutter