Навигатор#

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

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

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

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

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

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

  • и т.п.

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

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

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

  • GsBottomNavigationBarView

  • GsDrawerNavigationView

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

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

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

    • 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 обеспечивает плавные переходы, блокировки, меню и коммуникацию между экранами — всё в нескольких вызовах без шаблонного кода.