Вопрос или проблема
Я использую Состояние вложенных маршрутов
с GoRouter
Я следовал этому руководству: https://codewithandrea.com/articles/flutter-bottom-navigation-bar-nested-routes-gorouter/
Навигация работает хорошо.
У меня есть маршрут /profile
и маршрут, заключенный в профиль: /profile/settings
Профиль заключен в виджет:
class ScaffoldWithNestedNavigation extends StatelessWidget {
const ScaffoldWithNestedNavigation({
Key? key,
required this.navigationShell,
}) : super(key: key ?? const ValueKey('ScaffoldWithNestedNavigation'));
final StatefulNavigationShell navigationShell;
void _goBranch(int index) {
navigationShell.goBranch(
index,
initialLocation: index == navigationShell.currentIndex,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: navigationShell,
bottomNavigationBar: NavigationBar(
selectedIndex: navigationShell.currentIndex,
destinations: const [
NavigationDestination(icon: Icon(Icons.home_rounded), label: 'Главная'),
NavigationDestination(icon: Icon(Icons.person_rounded), label: 'Профиль'),
],
onDestinationSelected: _goBranch,
),
);
}
}
Моя проблема в том, что когда я делаю context.go('/profile/settings')
из профиля, он перенаправляет меня в настройки, но сохраняет NavigationBar
. Я понимаю, что это логично, так как он все еще заключен в ScaffoldWithNestedNavigation
.
Как я могу сделать так, чтобы это было на отдельном экране, но все еще приходило из маршрута профиля?
Например, я ищу такое же поведение, как в Discord
. Чтобы протестировать: перейдите в профиль -> нажмите на иконку настроек в правом верхнем углу -> экран настроек появляется слева без навигационной панели.
Я пытался сделать отдельный экран для `/settings` и переопределить поп, чтобы вернуться к /profile.
- Это неаккуратно и не поддерживаемо, так как мне нужно делать это для каждого экрана, который не имеет навигационной панели. Если я изменю свои маршруты, мне нужно будет пройтись по всем маршрутам.
- Анимация перехода экранов нормально, но при возврате, так как не сохраняется экран профиля в стеке, он просто переходит на экран профиля и воспроизводит навигацию (так как не сохраняет экран профиля).
Я не могу использовать состояние с showNavigationBar
? Когда я добавляю новые экраны, это не будет плавно, когда я открываю экраны без navigationBar
.
Ответ или решение
Для решения проблемы с отображением нижней панели навигации в Flutter при использовании Stateful Nested Routes с GoRouter, необходимо изменить подход к маршрутизации и управлению состоянием. Ваша цель заключается в том, чтобы иметь возможность переходить на экран настроек из профиля, не отображая при этом нижнюю панель навигации, однако при этом сохранить "поток" навигации между этими экранами.
Решение
-
Создание отдельного маршрута для экрана настроек:
Вместо того чтобы помещать экран настроек внутрь компонента с нижней навигационной панелью, создайте отдельный маршрут для/settings
. Это позволит вам легко управлять состоянием и не отображать нижнюю панель.Пример определения маршрутов:
final GoRouter _router = GoRouter( routes: <RouteBase>[ ShellRoute( navigatorKey: _shellNavigatorKey, builder: (context, state, child) { return ScaffoldWithNestedNavigation(navigationShell: child); }, routes: <RouteBase>[ GoRoute( path: '/profile', builder: (BuildContext context, GoRouterState state) => ProfileScreen(), routes: <RouteBase>[ GoRoute( path: 'settings', builder: (BuildContext context, GoRouterState state) => SettingsScreen(), ), ], ), GoRoute( path: '/home', builder: (BuildContext context, GoRouterState state) => HomeScreen(), ), ], ), GoRoute( path: '/settings', builder: (BuildContext context, GoRouterState state) => SettingsScreen(), ), ], );
-
Переход на экран настроек:
Вместо использованияcontext.go('/profile/settings')
, вы можете использоватьcontext.go('/settings')
, чтобы переходить на отдельный экран настроек. Так вы сможете избавиться от нижней панели навигации:IconButton( icon: Icon(Icons.settings), onPressed: () { context.go('/settings'); }, );
-
Управление возвратом:
Убедитесь, что ваше поведение возврата на экран профиля должным образом настраивается. Когда пользователь нажимает кнопку "назад" на экране настроек, он должен вернуться в профиль. Для этого создайте явный маршрут возвращения, если он не требуется, то просто используйтеcontext.go('/profile')
. -
Проверка состояния навигации:
Используйте состояниеshowNavigationBar
(или альтернативное состояние) для управления показом нижней панели навигации на основании текущего маршрута. Например, вы можете использоватьModalRoute.of(context)?.settings.name
для определения текущей страницы и решения, отображать ли панель навигации или нет.
Заключение
Следуя вышеизложенным шагам, вы сможете создать более чистую и поддерживаемую систему навигации в вашей Flutter-приложении. Это позволит вам интегрировать маршруты, которые могут отображаться без нижней навигационной панели, при этом сохраняя возможность перехода в нужные экраны. Такой подход поможет избежать повторяющегося кода и упростит управление состоянием вашего приложения.