Irbisa · Шпаргалка
Навигация и маршрутизация
Navigator, именованные маршруты, go_router, передача данных между экранами
Что такое
Navigator, что такое маршрут (route) и как работаютpushиpop?// Open a screen on top of the current oneNavigator.of(context).push( MaterialPageRoute(builder: (_) => const DetailsPage()),); // Close the top screen…Чем отличаются
push,pushReplacement,pushAndRemoveUntilиpopUntilи что использовать после логина?// Swap only the top routeNavigator.pushReplacement( context, MaterialPageRoute(builder: (_) => const HomePage()),);…Как передать данные на новый экран и получить результат обратно?
// Forward: constructorNavigator.push( context, MaterialPageRoute(builder: (_) => DetailsPage(userId: '123')),);…ColorPickerPageзакрывается черезNavigator.pop(context, 'red'), но пользователь уходит системной кнопкой «назад». Что выведет этот код?Future<void> pickColor(BuildContext context) async { final color = await Navigator.push<String>( context, MaterialPageRoute(builder: (_) => const ColorPickerPage()), ); print('picked: $color');}Как работают именованные маршруты и как обработать маршрут с параметром вроде
/product/42черезonGenerateRoute?MaterialApp( routes: { '/': (_) => const HomePage(), '/settings': (_) => const SettingsPage(), }, onGenerateRoute: (settings) {…Нажатие на эту кнопку падает с «Navigator operation requested with a context that does not include a Navigator»: почему?
class App extends StatelessWidget { const App({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: ElevatedButton( onPressed: () => Navigator.of(context).push( MaterialPageRoute(builder: (_) => const NextPage()), ), child: const Text('Go'), ), ), ); }}Как
showDialog,showModalBottomSheetиshowMenuвписываются в стек навигации?final confirmed = await showDialog<bool>( context: context, barrierDismissible: false, builder: (dialogContext) => AlertDialog( title: const Text('Delete account?'), actions: […Как перехватить кнопку «назад», чтобы подтвердить уход с экрана с несохранёнными изменениями (
PopScope, ранееWillPopScope)?class _EditProfileState extends State<EditProfilePage> { bool _dirty = false; @override Widget build(BuildContext context) { return PopScope(…Что такое Navigator 2.0 (Router API), чем он отличается от Navigator 1.0 и зачем его ввели?
class _AppState extends State<App> { Order? _selected; // the stack is a function of this state @override Widget build(BuildContext context) { return Navigator(…В
go_routerчем отличаютсяcontext.go()иcontext.push()?final router = GoRouter( routes: [ GoRoute( path: '/orders', builder: (context, state) => const OrdersPage(), routes: […Как сделать нижнюю навигацию, где каждая вкладка сохраняет своё состояние и свой стек «назад»?
final router = GoRouter( initialLocation: '/home', routes: [ StatefulShellRoute.indexedStack( builder: (context, state, shell) => Scaffold( body: shell, // keeps every branch alive…Найдите баг: после переезда
OrderPageво вкладку нижней навигации нажатие No закрывает экран заказа, а диалог остаётся открытым.Future<bool?> confirmCancel(BuildContext context) => showDialog<bool>( context: context, builder: (_) => AlertDialog( title: const Text('Cancel this order?'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('No'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('Yes'), ), ], ), );Как защитить маршруты авторизацией в
go_router?class AuthController extends ChangeNotifier { AuthStatus status = AuthStatus.loading; // loading, signedIn, signedOut void update(AuthStatus s) { status = s; notifyListeners(); }} GoRouter buildRouter(AuthController auth) => GoRouter(…Найдите баг: после переключения на тёмную тему на экране настроек приложение возвращается на главный экран.
class App extends StatelessWidget { const App({super.key, required this.theme}); final ValueNotifier<ThemeMode> theme; @override Widget build(BuildContext context) => ValueListenableBuilder( valueListenable: theme, builder: (context, mode, _) => MaterialApp.router( themeMode: mode, routerConfig: GoRouter(routes: [ GoRoute(path: '/', builder: (_, __) => const HomePage()), GoRoute(path: '/settings', builder: (_, __) => const SettingsPage()), ]), ), );}Каким будет стек после выполнения этого кода, какой экран окажется сверху и что покажет следующее «назад»?
// the stack starts as [Home]final nav = Navigator.of(context);nav.pushNamed('/a');nav.pushNamed('/b');nav.pushNamed('/c');nav.pushReplacementNamed('/d');nav.pop();Как настроить deep links, Android App Links и iOS Universal Links во Flutter-приложении?
<!-- android/app/src/main/AndroidManifest.xml, inside the main activity --><intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data…Пользователь тапнул push-уведомление, и нужно открыть конкретный экран. Как навигировать, если под рукой нет
BuildContext?final navigatorKey = GlobalKey<NavigatorState>(); MaterialApp(navigatorKey: navigatorKey, home: const HomePage()); // From a service: no context neededvoid openOrder(String id) {…Flutter web-приложение показывает URL вида
example.com/#/orders/42, а после перехода на чистые пути обновление страницы даёт 404: что происходит?Как сделать свой переход между страницами и что такое
animationиsecondaryAnimation?Route<T> fadeScaleRoute<T>(Widget page) { return PageRouteBuilder<T>( transitionDuration: const Duration(milliseconds: 280), reverseTransitionDuration: const Duration(milliseconds: 220), pageBuilder: (context, animation, secondaryAnimation) => page, transitionsBuilder: (context, animation, secondaryAnimation, child) {…Как работают Hero-анимации и какие у них типичные подводные камни?
// List screenListTile( leading: Hero( tag: 'product-${product.id}', // unique per item child: Image.network(product.thumbUrl, width: 56, height: 56), ),…Как экран узнаёт, что поверх него положили другой маршрут, например, чтобы поставить видео на паузу?
final routeObserver = RouteObserver<PageRoute<void>>();// MaterialApp(navigatorObservers: [routeObserver], ...) class _PlayerPageState extends State<PlayerPage> with RouteAware { late final VideoPlayerController _controller = widget.controller;…На медленном телефоне пользователь дважды тапает по строке списка, и в стек попадают два одинаковых экрана деталей: как это предотвратить?
class _OrderListState extends State<OrderList> { bool _navigating = false; Future<void> _open(Order order) async { if (_navigating) return; // second tap is ignored _navigating = true;…Deep link на товар открывает экран товара, но «назад» закрывает приложение вместо перехода в каталог. Как восстановить нормальный стек «назад»?
final router = GoRouter( routes: [ GoRoute( path: '/', builder: (_, __) => const HomePage(), routes: […Android убивает приложение в фоне, и когда пользователь возвращается, стек глубиной в три экрана пропал. Как его восстановить?
void main() => runApp(const MaterialApp( restorationScopeId: 'app', // without this nothing is restored home: OrderListPage(), )); // Top-level and annotated: saved as a reference plus its arguments…