Переход между экранами и временный слой — разные задачи.
Экран приложения
Маршрут участвует в истории. Back возвращает предыдущий экран вместе с его локальным состоянием.
Временный интерфейс
Диалог, меню, toast или drawer показываются над текущим маршрутом и закрываются независимо.
Создайте области один раз.
Controller хранит изменяемый стек, поэтому он должен принадлежать приложению или StatefulWidget. Host только отображает состояние своего controller.
private readonly Navigator _navigator =
new(new DashboardPage());
private readonly OverlayController _overlay = new();
new BackNavigation(
new OverlayHost(
new NavigatorHost(_navigator), _overlay),
_navigator, _overlay);Повторный Build создаст пустой стек и потеряет прежнюю историю. Controller должен переживать перестроения описания.
Push сохраняет историю. Replace заменяет текущую вершину.
Используйте Push, когда пользователь должен вернуться назад. Используйте Replace после входа, onboarding или другого шага, возврат к которому не имеет смысла.
_navigator.Push(new Route(
new WidgetKey($"project:{project.Id}"),
new ProjectDetails(project),
RouteTransition.Fade(
TimeSpan.FromMilliseconds(180))));Key маршрута нужен, когда его идентичность важна для восстановления или поиска в стеке. Он должен описывать конкретный логический экран.
Верхний modal получает ввод вместо содержимого под ним.
Если пользователь обязан принять решение, запретите закрытие кликом по barrier и кнопкой Back. Закройте modal через возвращённый handle или действие внутри диалога.
_overlay.ShowModal(
new Dialog(
new Text("Удалить проект?")),
new ModalOptions(
dismissOnBarrier: false,
dismissOnBack: false));Back закрывает верхнюю область первой.
BackNavigation обрабатывает действие в порядке: верхний overlay, активный route, затем ничего на корневом экране. Поэтому Escape не проходит сквозь открытый диалог к маршруту под ним.
Храните только ту историю, которая нужна пользователю.
Неактивные маршруты остаются смонтированными, чтобы сохранить локальное состояние. Это полезно, но бесконечный стек удерживает деревья и данные.
Используйте Replace, PopToRoot или ClearAndPush в потоках, которым не нужен полный back stack.