Перейти к основному содержанию
`Ctrl`+`K`

# Навигатор

Класс, отвечающий за стандартное поведение пользовательского экрана:

- компоновка панелей и текущего представления

- перерисовка элементов

- блокировка экрана

- показ диалогов

- работа с меню и внутренней шиной событий

- и т.п.

Контроллер представления получает доступ к навигатору через свойство `navigator`.

Контроллер представления может изменить стандартное поведение, переопределив соответствующие методы.
Перечень методов для переопределения определён в интерфейсе `NavigableVcp`.

Классы, реализующие навигатор:

- `GsBottomNavigationBarView`

- `GsDrawerNavigationView`

## Пользовательский Navigator

Фреймворк поставляет базовую реализацию, но вы можете создать свою, реализовав интерфейс `Navigator` и передав её в `GsBaseActivity.provideNavigator()`.
Все контроллеры продолжат работать: интерфейс стабилен.

## Отображение экрана

Экран отрисовывается на основе следующих элементов:

- Контроллер представления
  Используется контроллер представления верхнего состояния в стеке состояний.

  - `View` — разметка на основе библиотеки Compose

  - `NavigableVcp` — инъекция зависимости в навигатор, которая может переопределить стандартное поведение:

    - состав меню

    - видимость меню

    - FAB

    - наименование экрана

- `TopBar`

- `BottomBar`

- `Drawer`
  Только в случае `GsDrawerNavigationView`

- диалоговые окна

- загрузочные окна

В стеке никогда не хранится более одного экрана для каждого `SmState`.
Повторный вызов `State` просто обновляет существующий элемент.

## TopBar

Плашка вверху экрана, используется для:

- навигационной кнопки
  Часто используется для кнопки вызова меню или кнопки «назад».

- наименования экрана

- кнопок действий

Для понимания принципов использования смотрите `AppBar` в `Google Material Design`.

Функции навигатора:

- `hideTopAppBar()`

- `showTopAppBar()`

- `topGsMenuItems`

## BottomBar

Плашка внизу экрана, используется для:

- кнопок глобальной навигации

Для понимания принципов использования смотрите `NavigationBar` в `Google Material Design`.

Функции навигатора:

- `hideBottomBar()`

- `showBottomBar()`

- `setBadgeFor(vciClassName, value)`
  В случае `GsBottomNavigationBarView` задаёт индикацию глобальным переходам.

## Drawer

Выезжающая боковая панель, используется для глобальных переходов и действий.

## Список глобальных переходов

Задаёт доступные переходы в состояния, которые пользователь может выполнить из
`Drawer` или `BottomBar` в зависимости от используемого навигатора.

Функции навигатора:

- `setBaseMenu()`

## FAB

Плавающая кнопка, которая размещается поверх интерфейса и предназначена для выполнения главного действия на экране.

По умолчанию иконка `+` выключена. Переопределяется в `NavigableVcp`.

## Блокировка и диалоги

Функции навигатора:

- `lock("Sync…")` — показывает полноэкранный индикатор и блокирует навигационные жесты

- `unlock()` — снимает блокировку
  Это удобно для сетевых операций, которые важно завершить без выхода пользователя.

- `createDialog(title, msg, …)` — упрощённый API для простых диалогов «OK/Cancel»
  Данные хранятся в `navigator.simpleDialog`, Compose-слой реагирует автоматически.

## Шина событий

Навигатор предоставляет компактную шину событий (на основе `Flow` Kotlin) между независимыми
контроллерами представлений без глобальных синглтонов.

Функции контроллера представления:

- `subscribeEventBus`

      // подписка
      vci.subscribeEventBus<MyPayload>("UpdateEvent") { payload ->
          // реакция
      }

- `sendEventBus`

      // публикация
      vci.sendEventBus("UpdateEvent", MyPayload(...)) { error ->
          // обработка ошибок
      }

Примечание

- За каждым именем события хранится `SharedFlow`.

- При закрытии экрана `closeEventBus(name)` автоматически отменяет подписку, предотвращая утечки.

## Индикатор синхронизации

Функции навигатора:

- `setNeedSync(boolean)`
  Включает или выключает иконку «обновить» в `TopBar`.

- `onClickSyncBtn`
  Передаёт обработчик в текущий `VCI`; типичная реализация — вызов `postSharedTask` для синхронизации с сервером.

## Примечание

### Пример расширения Navigator

Пример расширения для работы с NFC:

    class MyNavigator :
        NavigatorCtrl(),
        NavigatorNfc {

        override fun <T> onNfcRead(
            data: String,
            ss: SmStateSubject<out SmState>,
            onRead: (String) -> Unit,
            onShow: (T) -> Unit
        ) {
            // обработка NFC-данных
        }
    }

    interface NavigatorNfc {
        fun <T> onNfcRead(
            data: String,
            ss: SmStateSubject<out SmState>,
            onRead: (String) -> Unit = {},
            onShow: (T) -> Unit = {}
        )
    }

    // MainActivity

    navigator.onNfcRead<Map<String, String>>(it, getSts()) { data ->
        nfcData = data
        showNfcDialog.value = true
    }

### Пример MainActivity

    class MainActivity : GsBaseActivity<AppNavigator>() {

        @Composable
        override fun ContentView(navigatorCtrl: NavigatorCtrl) {
            AppTheme {
                navigator.setBaseMenu(
                    listOf(
                        DrawerItem("Users") { getSts().postCallState<UsersState>() },
                        DrawerItem("Settings") { getSts().postCallState<SettingsState>() }
                    )
                )
                GsDrawerNavigatorView(navigatorCtrl)
            }
        }

        override fun provideNavigator()  = AppNavigator()
        override fun provideDatabase()   = AppDatabase.getInstance(this)
        override fun provideFirstState() = UsersState()
    }

Главная Activity предоставляет `Navigator`, базовое меню и первое состояние; дальше всё управление переходит к `StateManager` и VCI-слою.

Навигационный слой GMF изолирует UI-логику от бизнес-кода: контроллеры формируют интеракции, а `Navigator` обеспечивает плавные переходы, блокировки, меню и коммуникацию между экранами — всё в нескольких вызовах без шаблонного кода.