Navigation and Routing
Master screen transitions, named routes, and passing data between pages.
Named Routes
Define routes in MaterialApp and navigate by name:
app.dart
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => const HomeScreen(),
'/products': (context) => const ProductListScreen(),
'/settings': (context) => const SettingsScreen(),
},
)
// Navigate by name
Navigator.pushNamed(context, '/products');
Passing Arguments
Use onGenerateRoute to handle complex route arguments:
routes.dart
class AppRouter {
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case '/product-detail':
final args = settings.arguments as ProductArgs;
return MaterialPageRoute(
builder: (_) => ProductDetailScreen(product: args.product),
);
case '/settings':
return MaterialPageRoute(builder: (_) => const SettingsScreen());
default:
return MaterialPageRoute(builder: (_) => const HomeScreen());
}
}
}
// Navigate with arguments
Navigator.pushNamed(context, '/product-detail',
arguments: ProductArgs(product: selectedProduct),
);
Real-World Example: Product List → Detail
product_flow.dart
// Product List Screen
class ProductListScreen extends StatelessWidget {
const ProductListScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Products')),
body: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return ListTile(
title: Text('Product ${index + 1}'),
subtitle: Text('\$${(index + 1) * 9.99}'),
trailing: const Icon(Icons.chevron_right),
onTap: () => Navigator.pushNamed(
context, '/product-detail',
arguments: ProductArgs(
product: Product('p_${index}', 'Product ${index + 1}', (index + 1) * 9.99),
),
),
);
},
),
);
}
}
// Product Detail Screen
class ProductDetailScreen extends StatelessWidget {
final Product product;
const ProductDetailScreen({super.key, required this.product});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(product.name)),
body: Column(children: [
Text(product.name, style: Theme.of(context).textTheme.headlineMedium),
Text('\$${product.price.toStringAsFixed(2)}',
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: const Text('← Back to Products'),
),
]),
);
}
}
Summary
Navigator.push/popfor imperative navigation- Named routes for cleaner route definitions
onGenerateRoutefor complex argument passing- Navigator 2.0 for deep linking and declarative routing
🚀 Next Step Continue to Local Data Persistence.