Введение

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

Одной из обсуждаемых тем стало: «Следует ли диалог отображаться через навигацию и сохраняться как часть истории пользовательской навигации?» Мой ответ: «Это зависит от того, что именно мы подразумеваем под диалогом».

Меня зовут Кирилл Розов, и в этой статье я расскажу, что я понимаю под диалогом в Material Design и как, на мой взгляд, стоит работать с ними в системе навигации.

Если вам интересно следить за самыми последними новостями Android разработки и получать подборку интересных статей по этой тематике, тогда вам стоит подписаться на Телеграм-канал Android Broadcast и мой YouTube канал "Android Broadcast"

Что такое диалог

Диалог в пользовательском интерфейсе (UI — User Interface) — это всплывающее окно, панель или экран, который временно отображается поверх основного содержимого приложения или сайта.

image.png
Диалог выбора даты

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

Не следует путать диалоги с экранами, которые просто не занимают весь дисплей устройства. Например, распространённый подход — показывать диалог во весь экран на смартфонах, тогда как на планшетах его отображают по центру, занима�� лишь часть дисплея. При этом экран на планшете не становится диалогом, даже если визуально напоминает его. В Material Design отображение во весь экран на телефоне называется “полноэкранный диалог”.

Полноэкранный диалог на смартфоне и модальный диалог на планшете
Полноэкранный диалог на смартфоне и обычный на планшете
image.png
Диалог выбора в виде Bottom Sheet

В Material Design есть компоненты Bottom Sheet (используемый на смартфонах и планшетах) и Side Sheet (применяемый на больших экранах), которые также можно считать разновидностью диалогов, так как они выполняют аналогичные функции: предоставляют возможность взаимодействия и передачи информации, не покидая текущий экран. Эти компоненты используются для выполнения задач, для которых обычно применяются диалоги, и могут служить для отображения дополнительной информации, настроек или параметров, сохраняя при этом контекст основного интерфейса.

Screenshot 2024-10-23 at 16.23.49.png
Side Sheet - версия Bottom Sheet для больших экранов
Контекстное меню в Android
Контекстное меню в Android

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

Модальность диалога

Четкого разделения по месту использования диалогов нет, но их можно классифицировать по влиянию на взаимодействие с интерфейсом — на модальные и немодальные.

Пример диалога с подтверждением действия
Пример диалога с подтверждением действия

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

Пример немодального диалога
Пример немодального диалога

Немодальные диалоги позволяют пользователю продолжать работу с приложением, поскольку не требуют немедленного взаимодействия. К этой категории относятся такие элементы, как Подсказки или Уведомления, часто реализованные в виде баннеров или Snackbar. Они отображаются ненавязчиво, предоставляя информацию или дополнительные опции, но не блокируют основной интерфейс и не прерывают рабочий процесс пользователя.

Диалог в навигации: быть или не быть

Под навигацией пользователя в UI я понимаю переход по Экранам приложения. История навигации возвращается после восстановления приложения. Потеря любого из такого элемента навигации критичная для пользователя.

Если рассмотреть библиотеку навигации Jetpack Navigation для Compose, то прямо в документации метода dialog() говорится:

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

Показ Экрана в виде диалог коде Jetpack Navigation хоть и выделен функций, но это ��ишь визуальная обертка в Dialog и по сути имеет мало разницы с показом обычного Экрана

// Пример использования Jetpack Navigation для показа Composable
// во всплывающем окне в стиле диалога
NavHost(
  navController = navController,
  startDestination = startDestination,
  modifier = modifier
) {
    dialog<PopupScreen>{
      // Показываем Composable функцию, которую обернут в диалог
    }
    composable {
      // Показ Composable функции на всём доступном пространстве
    }
  }

В итоге я для себя сформулировал несколько правил, касающихся экранов в навигации:

  • Все контекстные элементы UI, такие как контекстное меню, не относятся к навигации.

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

  • Диалоги подтверждения и выбора не считаются частью навигации, так как их задача — предотвращение случайных действий; они привязаны к контексту экрана и могут являться частью состояния экрана.

  • Экран приложения, отображаемый в стиле диалога, является частью навигации. Здесь диалог — это лишь визуальный стиль, накладываемый на экран. На некоторых устройствах такой экран может занимать всё доступное пространство.

  • Контент приложения, представленный в стиле диалога, считается частью навигации, так как сохраняется при переходах между экранами и добавляется в стек навигации (back stack).

В своём решение навигации выделять работу с диалогами я не вижу смысла, так это лишь визуальный стиль Экрана в состоянии навигации, за который должна отвечать UI часть навигации.

Мне интересно узнать ваше мнение и как вы подходите к работе с диалогами в UI навигации. Делитесь им в комментариях и давайте искать истину вместе!