Постоянный виджет на всех экранах с помощью Flutter Navigator

В большинстве современных приложений есть нижняя панель навигации или боковая панель навигации, которые иногда необходимо сохранять при переходе на новый экран.

Но проблема с обычной флаттер-навигацией заключается в том, что когда вы нажимаете новый маршрут, нижняя навигация не сохраняется с ним. Позвольте показать вам на примере.

Другой вариант использования для веб-приложения: если нам нужна боковая панель навигации, и мы реализуем ее, изменив текущий отображаемый экран, тогда пользователь не сможет перейти непосредственно к определенной вкладке. URL-адреса не будут привязаны к каждой вкладке.
Пример: https://www.facebook.com/ и https://www.facebook.com/watch - это две разные вкладки facebook, к которому можно получить доступ напрямую, используя URL-адрес или нажав на панели навигации.

Еще один вариант использования, что, если вы хотите, чтобы виджет отображался рядом с каждым экраном? Размещение одного и того же виджета на каждом экране будет работать, но это немного утомительная задача.

Для решения этих проблем мы будем использовать Navigator виджет, предоставляемый flutter. Используя этот виджет, мы могли бы контролировать, какая часть экрана должна использоваться каркасом для навигации.

Давайте посмотрим, как это сделать, на простом примере.

Здесь мы создадим две вещи:
1. BaseWidget
2. PersistentWidget

BaseWidget

Этот виджет принимает дочерний виджет и показывает дочерний виджет и постоянный виджет в столбце. Вы можете использовать свой собственный макет в этом виджете.

Переданный child - это экран навигации, и нам нужно, чтобы он занимал все пространство, поэтому он заключен в Expanded виджет.

class BaseWidget extends StatelessWidget {
  final Widget child;
  const BaseWidget({this.child});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Expanded(child: child),
          PersistentWidget(),
        ],
      ),
    );
  }
}

PersistentWidget

Это виджет, который мы хотим отображать на всех экранах. Я создал виджет, который позволяет пользователям проверять предложение с любого экрана.

class PersistentWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 40.0,
      margin: EdgeInsets.all(10.0),
      decoration: BoxDecoration(borderRadius: BorderRadius.all(new Radius.circular(10.0)),
        gradient: LinearGradient(colors: [Colors.yellow[700], Colors.redAccent],
          begin: Alignment.centerLeft, end: Alignment.centerRight, tileMode: TileMode.clamp)),
      child: Center(child: Text('Tap to know about our exciting new offer!', style: TextStyle(fontSize: 16.0, color: Colors.white70, fontWeight: FontWeight.bold), ), ),
    );
  }
}

Я создал три фиктивных экрана с именами FirstScreen, SecondScreen и ThirdScreen. На первом и втором экранах есть кнопки для перехода к следующему экрану.

Основная часть

MaterialApp предоставляет конструктор, который предоставит нам текущий виджет экрана с навигацией. Мы можем передать этот виджет через наш BaseWidget, чтобы получить желаемый макет.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      builder: (context, child) => BaseWidget(child: child),
      initialRoute: '/',
      routes: {
        '/': (context) => FirstScreen(),
        '/second': (context) => SecondScreen(),
        '/third': (context) => ThirdScreen(),
      },
    );
  }
}

Я определил именованные маршруты с начальным маршрутом как FirstScreen.

Теперь, когда любой экран помещается в стек, он проходит через наш BaseWidget. BaseWidget разместит экран, а PersistentWidget в столбце.

Результат

Как видите, PersistentWidget присутствует на всех экранах, даже если мы перейдем на другой экран.

Та же логика может использоваться для реализации постоянной нижней панели навигации или постоянной боковой панели.

Надеюсь, это короткое и простое руководство было для вас полезным.

Спасибо, что дочитали до этого момента. Не забудьте оставить комментарий для любых предложений и 👏 для этой истории.