Files

267 lines
6.2 KiB
Markdown
Raw Permalink Normal View History

# Flutter Navigation and Routing: A Comprehensive Guide
Navigation and routing are essential for creating multi-screen applications in Flutter. This guide covers both Navigator 1.0 and 2.0 approaches, as well as named routes and generated routes.
## 1. Navigator 1.0
Navigator 1.0 is the traditional way of handling navigation in Flutter.
### Basic Navigation
```dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: FirstScreen(),
);
}
}
class FirstScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('First Screen')),
body: Center(
child: ElevatedButton(
child: Text('Go to Second Screen'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
},
),
),
);
}
}
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Second Screen')),
body: Center(
child: ElevatedButton(
child: Text('Go back'),
onPressed: () {
Navigator.pop(context);
},
),
),
);
}
}
```
### Named Routes
```dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => HomeScreen(),
'/details': (context) => DetailsScreen(),
},
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home')),
body: Center(
child: ElevatedButton(
child: Text('Go to Details'),
onPressed: () {
Navigator.pushNamed(context, '/details');
},
),
),
);
}
}
class DetailsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Details')),
body: Center(
child: ElevatedButton(
child: Text('Go back'),
onPressed: () {
Navigator.pop(context);
},
),
),
);
}
}
```
## 2. Navigator 2.0
Navigator 2.0 provides a more declarative approach to navigation.
### Example:
```dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final RouteInformationParser<List<String>> _routeInformationParser = MyRouteInformationParser();
final RouterDelegate<List<String>> _routerDelegate = MyRouterDelegate();
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Navigator 2.0 Demo',
routerDelegate: _routerDelegate,
routeInformationParser: _routeInformationParser,
);
}
}
class MyRouteInformationParser extends RouteInformationParser<List<String>> {
@override
Future<List<String>> parseRouteInformation(RouteInformation routeInformation) async {
final uri = Uri.parse(routeInformation.location!);
return uri.pathSegments;
}
@override
RouteInformation restoreRouteInformation(List<String> configuration) {
return RouteInformation(location: '/' + configuration.join('/'));
}
}
class MyRouterDelegate extends RouterDelegate<List<String>>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<List<String>> {
final List<String> _stack = [''];
@override
final navigatorKey = GlobalKey<NavigatorState>();
List<String> get stack => List.unmodifiable(_stack);
@override
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
pages: [
MaterialPage(
key: ValueKey('HomePage'),
child: HomePage(
onPush: (String value) {
_stack.add(value);
notifyListeners();
},
),
),
if (_stack.length > 1)
MaterialPage(
key: ValueKey('DetailsPage'),
child: DetailsPage(
data: _stack.last,
onPop: () {
_stack.removeLast();
notifyListeners();
},
),
),
],
onPopPage: (route, result) {
if (!route.didPop(result)) {
return false;
}
if (_stack.length > 1) {
_stack.removeLast();
notifyListeners();
}
return true;
},
);
}
@override
Future<void> setNewRoutePath(List<String> configuration) async {
_stack
..clear()
..addAll(configuration);
notifyListeners();
}
}
class HomePage extends StatelessWidget {
final void Function(String) onPush;
HomePage({required this.onPush});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home')),
body: Center(
child: ElevatedButton(
child: Text('Go to Details'),
onPressed: () => onPush('details'),
),
),
);
}
}
class DetailsPage extends StatelessWidget {
final String data;
final VoidCallback onPop;
DetailsPage({required this.data, required this.onPop});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Details')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Details for: $data'),
ElevatedButton(
child: Text('Go back'),
onPressed: onPop,
),
],
),
),
);
}
}
```
## Conclusion
Understanding both Navigator 1.0 and 2.0 approaches is crucial for effective navigation in Flutter applications. While Navigator 1.0 is simpler and sufficient for many apps, Navigator 2.0 offers more control and is especially useful for web applications and complex navigation scenarios.