Не отображайте нижнюю панель навигации Flutter с вложенными маршрутами Stateful, используя GoRouter.

Вопрос или проблема

Я использую Состояние вложенных маршрутов с 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.

  1. Это неаккуратно и не поддерживаемо, так как мне нужно делать это для каждого экрана, который не имеет навигационной панели. Если я изменю свои маршруты, мне нужно будет пройтись по всем маршрутам.
  2. Анимация перехода экранов нормально, но при возврате, так как не сохраняется экран профиля в стеке, он просто переходит на экран профиля и воспроизводит навигацию (так как не сохраняет экран профиля).

Я не могу использовать состояние с showNavigationBar? Когда я добавляю новые экраны, это не будет плавно, когда я открываю экраны без navigationBar.

Ответ или решение

Для решения проблемы с отображением нижней панели навигации в Flutter при использовании Stateful Nested Routes с GoRouter, необходимо изменить подход к маршрутизации и управлению состоянием. Ваша цель заключается в том, чтобы иметь возможность переходить на экран настроек из профиля, не отображая при этом нижнюю панель навигации, однако при этом сохранить "поток" навигации между этими экранами.

Решение

  1. Создание отдельного маршрута для экрана настроек:
    Вместо того чтобы помещать экран настроек внутрь компонента с нижней навигационной панелью, создайте отдельный маршрут для /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(),
       ),
     ],
    );
  2. Переход на экран настроек:
    Вместо использования context.go('/profile/settings'), вы можете использовать context.go('/settings'), чтобы переходить на отдельный экран настроек. Так вы сможете избавиться от нижней панели навигации:

    IconButton(
     icon: Icon(Icons.settings),
     onPressed: () {
       context.go('/settings');
     },
    );
  3. Управление возвратом:
    Убедитесь, что ваше поведение возврата на экран профиля должным образом настраивается. Когда пользователь нажимает кнопку "назад" на экране настроек, он должен вернуться в профиль. Для этого создайте явный маршрут возвращения, если он не требуется, то просто используйте context.go('/profile').

  4. Проверка состояния навигации:
    Используйте состояние showNavigationBar (или альтернативное состояние) для управления показом нижней панели навигации на основании текущего маршрута. Например, вы можете использовать ModalRoute.of(context)?.settings.name для определения текущей страницы и решения, отображать ли панель навигации или нет.

Заключение

Следуя вышеизложенным шагам, вы сможете создать более чистую и поддерживаемую систему навигации в вашей Flutter-приложении. Это позволит вам интегрировать маршруты, которые могут отображаться без нижней навигационной панели, при этом сохраняя возможность перехода в нужные экраны. Такой подход поможет избежать повторяющегося кода и упростит управление состоянием вашего приложения.

Оцените материал
Добавить комментарий

Капча загружается...