added resources, coding challenges, and more study guides
This commit is contained in:
@@ -0,0 +1,267 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user