flutter-implementing-navigation-and-routing
"Handles routing, navigation, and deep linking in a Flutter application. Use when moving between screens or setting up URL-based navigation."
npx skills add flutter/skills --skill flutter-implementing-navigation-and-routingBefore / After 效果对比
0 组description 文档
name: "flutter-implementing-navigation-and-routing" description: "Handles routing, navigation, and deep linking in a Flutter application. Use when moving between screens or setting up URL-based navigation." metadata: model: "models/gemini-3.1-pro-preview" last_modified: "Thu, 12 Mar 2026 22:30:17 GMT"
Implementing Navigation and Routing in Flutter
Contents
- Core Concepts
- Implementing Imperative Navigation
- Implementing Declarative Navigation
- Implementing Nested Navigation
- Workflows
- Examples
Core Concepts
- Routes: In Flutter, screens and pages are referred to as routes. A route is simply a widget. This is equivalent to an
Activityin Android or aViewControllerin iOS. - Navigator vs. Router:
- Use
Navigator(Imperative) for small applications without complex deep linking requirements. It manages a stack ofRouteobjects. - Use
Router(Declarative) for applications with advanced navigation, web URL synchronization, and specific deep linking requirements.
- Use
- Deep Linking: Allows an app to open directly to a specific location based on a URL. Supported on iOS, Android, and Web. Web requires no additional setup.
- Named Routes: Avoid using named routes (
MaterialApp.routesandNavigator.pushNamed) for most applications. They have rigid deep linking behavior and do not support the browser forward button. Use a routing package likego_routerinstead.
Implementing Imperative Navigation
Use the Navigator widget to push and pop routes using platform-specific transition animations (MaterialPageRoute or CupertinoPageRoute).
Pushing and Popping
- Navigate to a new route using
Navigator.push(context, route). - Return to the previous route using
Navigator.pop(context). - Use
Navigator.pushReplacement()to replace the current route, orNavigator.pushAndRemoveUntil()to clear the stack based on a condition.
Passing and Returning Data
- Sending Data: Pass data directly into the constructor of the destination widget. Alternatively, pass data via the
settings: RouteSettings(arguments: data)parameter of thePageRouteand extract it usingModalRoute.of(context)!.settings.arguments. - Returning Data: Pass the return value to the
popmethod:Navigator.pop(context, resultData). Await the result on the pushing side:final result = await Navigator.push(...).
Implementing Declarative Navigation
For apps requiring deep linking, web URL support, or complex routing, implement the Router API via a declarative routing package like go_router.
- Switch from
MaterialApptoMaterialApp.router. - Define a router configuration that parses route paths and configures the
Navigatorautomatically. - Navigate using package-specific APIs (e.g.,
context.go('/path')). - Page-backed vs. Pageless Routes: Declarative routes are page-backed (deep-linkable). Imperative pushes (e.g., dialogs, bottom sheets) are pageless. Removing a page-backed route automatically removes all subsequent pageless routes.
Implementing Nested Navigation
Implement nested navigation to manage a sub-flow of screens (e.g., a multi-step setup process or persistent bottom navigation tabs) independently from the top-level global navigator.
- Instantiate a new
Navigatorwidget inside the host widget. - Assign a
GlobalKey<NavigatorState>to the nestedNavigatorto control it programmatically. - Implement the
onGenerateRoutecallback within the nestedNavigatorto resolve sub-routes. - Intercept hardware back button presses using
PopScopeto prevent the top-level navigator from popping the entire nested flow prematurely.
Workflows
Workflow: Standard Screen Transition
Copy this checklist to track progress when implementing a basic screen transition:
- [ ] Create the destination widget (Route).
- [ ] Define required data parameters in the destination widget's constructor.
- [ ] Implement
Navigator.push()in the source widget. - [ ] Wrap the destination widget in a
MaterialPageRouteorCupertinoPageRoute. - [ ] Implement
Navigator.pop()in the destination widget to return.
Workflow: Implementing Deep-Linkable Routing
Use this conditional workflow when setting up app-wide routing:
- [ ] If the app is simple and requires no deep linking:
- [ ] Use standard
MaterialAppandNavigator.push().
- [ ] Use standard
- [ ] If the app requires deep linking, web support, or complex flows:
- [ ] Add the
go_routerpackage. - [ ] Change
MaterialApptoMaterialApp.router. - [ ] Define the
GoRouterconfiguration with all top-level routes. - [ ] Replace
Navigator.push()withcontext.go()orcontext.push().
- [ ] Add the
Workflow: Creating a Nested Navigation Flow
Run this workflow when building a multi-step sub-flow (e.g., IoT device setup):
- [ ] Define string constants for the nested route paths.
- [ ] Create a
GlobalKey<NavigatorState>in the host widget's state. - [ ] Return a
Navigatorwidget in the host'sbuildmethod, passing the key. - [ ] Implement
onGenerateRoutein the nestedNavigatorto map string paths to specific step widgets. - [ ] Wrap the host
Scaffoldin aPopScopeto handle back-button interceptions (e.g., prompting "Are you sure you want to exit setup?"). - [ ] Use
navigatorKey.currentState!.pushNamed()to advance steps within the flow.
Examples
Example: Passing Data via Constructor (Imperative)
// 1. Define the data model
class Todo {
final String title;
final String description;
const Todo(this.title, this.description);
}
// 2. Source Screen
class TodosScreen extends StatelessWidget {
final List<Todo> todos;
const TodosScreen({super.key, required this.todos});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Todos')),
body: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(todos[index].title),
onTap: () {
// Push and pass data via constructor
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailScreen(todo: todos[index]),
),
);
},
);
},
),
);
}
}
// 3. Destination Screen
class DetailScreen extends StatelessWidget {
final Todo todo;
const DetailScreen({super.key, required this.todo});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(todo.title)),
body: Padding(
padding: const EdgeInsets.all(16),
child: Text(todo.description),
),
);
}
}
Example: Nested Navigation Flow
class SetupFlow extends StatefulWidget {
final String initialRoute;
const SetupFlow({super.key, required this.initialRoute});
@override
State<SetupFlow> createState() => _SetupFlowState();
}
class _SetupFlowState extends State<SetupFlow> {
final _navigatorKey = GlobalKey<NavigatorState>();
void _exitSetup() => Navigator.of(context).pop();
@override
Widget build(BuildContext context) {
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, _) async {
if (didPop) return;
// Intercept back button to prevent accidental exit
_exitSetup();
},
child: Scaffold(
appBar: AppBar(title: const Text('Setup')),
body: Navigator(
key: _navigatorKey,
initialRoute: widget.initialRoute,
onGenerateRoute: _onGenerateRoute,
),
),
);
}
Route<Widget> _onGenerateRoute(RouteSettings settings) {
Widget page;
switch (settings.name) {
case 'step1':
page = StepOnePage(
onComplete: () => _navigatorKey.currentState!.pushNamed('step2'),
);
break;
case 'step2':
page = StepTwoPage(onComplete: _exitSetup);
break;
default:
throw StateError('Unexpected route name: ${settings.name}!');
}
return MaterialPageRoute(
builder: (context) => page,
settings: settings,
);
}
}
forum用户评价 (0)
发表评价
暂无评价,来写第一条吧
统计数据
用户评分
为此 Skill 评分