Flutter Named Routes

Navigate between screens using route names

πŸ—ΊοΈ What are Named Routes?

Named Routes in Flutter allow you to navigate between screens using string identifiers instead of creating widget instances. This makes navigation cleaner, more maintainable, and easier to manage in large applications with multiple screens.


// Navigate using named route
Navigator.pushNamed(context, '/details');
                                    

Key Named Routes Concepts

πŸ“‹

Route Table

Define all routes in one place

routes: {
  '/home': (context) => HomePage(),
}
πŸš€

Push Named

Navigate to a named route

Navigator.pushNamed(
  context, '/profile'
);
πŸ“¦

Arguments

Pass data between routes

Navigator.pushNamed(
  context, '/user',
  arguments: userId
);
🏠

Initial Route

Set the starting screen

initialRoute: '/home'

πŸ”Ή Setting Up Named Routes

Define your routes in the MaterialApp widget:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Named Routes Demo',
      initialRoute: '/',
      routes: {
        '/': (context) => HomeScreen(),
        '/details': (context) => DetailsScreen(),
        '/profile': (context) => ProfileScreen(),
      },
    );
  }
}

Explanation:

initialRoute: The first screen to show ('/' is home)

routes: A map of route names to screen widgets

πŸ”Ή Basic Navigation

Navigate to a named route using pushNamed:

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // Navigate to details screen
            Navigator.pushNamed(context, '/details');
          },
          child: Text('Go to Details'),
        ),
      ),
    );
  }
}

class DetailsScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Details')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // Go back to previous screen
            Navigator.pop(context);
          },
          child: Text('Go Back'),
        ),
      ),
    );
  }
}

Result:

βœ… Clicking "Go to Details" navigates to DetailsScreen

βœ… Clicking "Go Back" returns to HomeScreen

πŸ”Ή Passing Arguments

Send data to named routes using arguments:

// Sending arguments
class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(
              context,
              '/user',
              arguments: 'John Doe', // Pass data
            );
          },
          child: Text('View User Profile'),
        ),
      ),
    );
  }
}

// Receiving arguments
class UserScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Get the arguments
    final String userName = ModalRoute.of(context)!.settings.arguments as String;
    
    return Scaffold(
      appBar: AppBar(title: Text('User Profile')),
      body: Center(
        child: Text('Welcome, $userName!'),
      ),
    );
  }
}

Output:

Screen displays: "Welcome, John Doe!"

πŸ”Ή Replace Current Route

Replace the current screen instead of adding to the stack:

// Use pushReplacementNamed for login flows
ElevatedButton(
  onPressed: () {
    Navigator.pushReplacementNamed(context, '/home');
    // User can't go back to login screen
  },
  child: Text('Login'),
)

When to use pushReplacementNamed:

  • After successful login (prevent going back to login)
  • After splash screen (remove splash from stack)
  • After onboarding (prevent returning to onboarding)

πŸ”Ή Remove All Routes

Clear the entire navigation stack:

// Navigate to home and remove all previous routes
ElevatedButton(
  onPressed: () {
    Navigator.pushNamedAndRemoveUntil(
      context,
      '/home',
      (route) => false, // Remove all routes
    );
  },
  child: Text('Logout'),
)

Use Case:

Perfect for logout functionality - clears all screens and goes to home

πŸ”Ή Complete Example

A full working example with multiple routes:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Named Routes App',
      initialRoute: '/',
      routes: {
        '/': (context) => HomeScreen(),
        '/about': (context) => AboutScreen(),
        '/contact': (context) => ContactScreen(),
      },
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => Navigator.pushNamed(context, '/about'),
              child: Text('About Us'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () => Navigator.pushNamed(context, '/contact'),
              child: Text('Contact'),
            ),
          ],
        ),
      ),
    );
  }
}

class AboutScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('About')),
      body: Center(child: Text('About Us Page')),
    );
  }
}

class ContactScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Contact')),
      body: Center(child: Text('Contact Us Page')),
    );
  }
}

🧠 Test Your Knowledge

Which method is used to navigate to a named route?