skills/flutter/references/features-navigation.md

5.0 KiB

name description
features-navigation Flutter navigation - Navigator.push, Navigator.pop, routes, and navigation patterns

Navigation

Flutter provides the Navigator widget for managing a stack of routes. Navigation allows users to move between different screens in your app.

Basic Navigation

Push a Route

// Navigate to a new screen
Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => const NextScreen(),
  ),
);

// With result
final result = await Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => const NextScreen(),
  ),
);

Pop a Route

// Pop current route
Navigator.of(context).pop();

// Pop with result
Navigator.of(context).pop('result data');

Complete Example

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            final result = await Navigator.of(context).push(
              MaterialPageRoute(
                builder: (context) => const DetailScreen(),
              ),
            );
            
            if (result != null) {
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('Result: $result')),
              );
            }
          },
          child: const Text('Go to Detail'),
        ),
      ),
    );
  }
}

class DetailScreen extends StatelessWidget {
  const DetailScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Detail')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.of(context).pop('Data from detail');
          },
          child: const Text('Go Back'),
        ),
      ),
    );
  }
}

Navigation Methods

pushReplacement

Replace the current route with a new one.

Navigator.of(context).pushReplacement(
  MaterialPageRoute(builder: (context) => const NewScreen()),
);

pushAndRemoveUntil

Push a new route and remove all previous routes until a condition is met.

// Navigate to home and remove all previous routes
Navigator.of(context).pushAndRemoveUntil(
  MaterialPageRoute(builder: (context) => const HomeScreen()),
  (route) => false, // Remove all routes
);

// Navigate to login and remove all routes except the first one
Navigator.of(context).pushAndRemoveUntil(
  MaterialPageRoute(builder: (context) => const LoginScreen()),
  (route) => route.isFirst, // Keep only the first route
);

popUntil

Pop routes until a condition is met.

// Pop until reaching home screen
Navigator.of(context).popUntil((route) => route.settings.name == '/home');

Route Types

MaterialPageRoute

Standard Material Design page transition.

Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => const NextScreen(),
    settings: const RouteSettings(
      name: '/detail',
      arguments: {'id': 123},
    ),
  ),
);

CupertinoPageRoute

iOS-style page transition.

Navigator.of(context).push(
  CupertinoPageRoute(
    builder: (context) => const NextScreen(),
  ),
);

PageRouteBuilder

Custom page transition.

Navigator.of(context).push(
  PageRouteBuilder(
    pageBuilder: (context, animation, secondaryAnimation) => const NextScreen(),
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      return FadeTransition(
        opacity: animation,
        child: child,
      );
    },
    transitionDuration: const Duration(milliseconds: 300),
  ),
);

Accessing Route Arguments

class DetailScreen extends StatelessWidget {
  const DetailScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)?.settings.arguments as Map<String, dynamic>?;
    final id = args?['id'] ?? 0;
    
    return Scaffold(
      appBar: AppBar(title: Text('Detail $id')),
      body: Center(
        child: Text('ID: $id'),
      ),
    );
  }
}

Navigation State

Check if Can Pop

if (Navigator.of(context).canPop()) {
  Navigator.of(context).pop();
} else {
  // Handle case where there's nothing to pop
}

Get Current Route

final route = ModalRoute.of(context);
final routeName = route?.settings.name;
final arguments = route?.settings.arguments;

Key Points

  • Use Navigator.push() to navigate forward
  • Use Navigator.pop() to go back
  • Pass data back using pop(result)
  • Use pushReplacement() to replace current route
  • Use pushAndRemoveUntil() for login/logout flows
  • Access route arguments via ModalRoute.of(context)?.settings.arguments
  • Check canPop() before popping to avoid errors