Перейти к основному содержимому

Android Compose

Android Compose (Jetpack Compose) — это набор инструментов для создания пользовательского интерфейса в Android-приложениях на языке программирования Kotlin. Основное отличие фреймворка от Android View — декларативный подход к описанию интерфейса.

Вы можете использовать модули для Android Compose от 2ГИС, чтобы добавить в свой проект стандартные UI-элементы:

  • compose-map для управления картой. Модуль доступен для обеих (Full и Map) версий SDK.
  • compose-navigation для создания навигатора. Модуль доступен только для полной (Full) версии SDK.

Чтобы подключить модуль в своё приложение, добавьте следующие элементы в app/build.gradle и укажите номер и тип версии SDK (оба параметра обязательны):

dependencies {

def sdkVersion = "13.0.0" // Номер версии SDK

implementation("ru.dgis.sdk:sdk-map:$sdkVersion") // Укажите sdk-map или sdk-full
implementation("ru.dgis.sdk:compose-map:$sdkVersion") // Модуль для карты
implementation("ru.dgis.sdk:compose-navigation:$sdkVersion") // Модуль для навигатора
}

Пример готового app/build.gradle см. в демо-проекте на GitHub.

Карта

Получите карту через MapComposable, чтобы в дальнейшем использовать её при добавлении UI-элементов. См. пример подготовки карты.

Стандартный набор элементов включает в себя:

  1. IndoorComposable для переключения этажей.
  2. TrafficComposable для показа текущего уровня пробок и для управления видимостью пробок на карте.
  3. ZoomComposable для масштабирования (приближения и отдаления) карты.
  4. CompassComposable для отображения текущего угла поворота карты относительно севера.
  5. MyLocationComposable для перелёта к текущему местоположению пользователя. Этот UI-элемент отображает текущее состояние слежения камеры (CameraFollowState) и позволяет изменять его.
  1. MinimapComposable для отображения мини-карты во время навигации.

Полная версия (Full) поставки SDK содержит набор UI-элементов для отображения и управления навигацией. Для удобства все элементы объединены в NavigationControlsComposable, который вы можете настраивать через DefaultNavigationControlsContent.

Стандартный набор элементов включает в себя:

  1. TrafficLineComposable для отображения уровня пробок на маршруте.
  2. ManeuverComposable для отображения информации о следующем манёвре.
  3. SpeedInfoComposable для отображения текущей скорости и скоростного ограничения.
  4. TrafficAndParkingComposable — контейнер для UI-элементов управления видимостью пробок (NavigatorTrafficComposable) и парковок (ParkingComposable) на карте.
  5. NavigationZoomComposable для масштабирования (приближения и отдаления) карты.
  6. NavigationCompassComposable для отображения текущего угла поворота карты относительно севера.
  7. NavigationFollowComposable для управления слежением за маркером местоположения.
  8. NavigationDashboardComposable для отображения информации в режиме ведения по маршруту.

 

  1. NavigationDashboardComposable для отображения информации в режиме свободной навигации.
  2. NavigationDashboardComposable для отображения информации в режиме навигации внутри зданий.
  3. NavigationIndoorComposable для управления списком этажей при навигации внутри здания.

  

  1. BetterRoutePromptComposable для отображения предложения о переходе на «маршрут лучше».
  2. FinishRouteComposable для отображения информации о завершении маршрута.
  3. RouteOverviewComposable для отображения общей информации о маршруте во время навигации.

Модуль compose-navigation содержит экраны и макеты компонентов для интерфейса настроек навигатора. Вы можете использовать готовый экран настроек, который открывается из дашборда навигации, или встроить отдельные компоненты в собственный экран приложения.

Настройки навигатора хранятся в NavigationSettingsRepository. Приложение создаёт и хранит экземпляр репозитория, а мобильный SDK использует экземпляр и читает из него настройки для управления навигатором и при построении маршрута. Используйте один и тот же репозиторий и в интерфейсе настроек навигатора, и в коде построения маршрута. Тогда значения, которые пользователь выбирает в настройках, будут доступны при создании RouteSearchOptions, и приложение учтёт их перед построением маршрута.

Если репозиторий передан в DefaultNavigationControlsState, часть настроек применяется к активной сессии навигации автоматически.

Готовый экран настроек

Создайте NavigationSettingsRepository и передайте его в DefaultNavigationControlsState. В примере ниже DefaultNavigationControlsState также применяет поддерживаемые динамические настройки к NavigationManager и учитывает их изменения во время навигации.

@Composable
fun NavigationControls(
context: Context,
map: Map,
navigationManager: NavigationManager,
minimapState: MapComposableState,
) {
val settingsRepository = remember(context) {
NavigationSettingsRepository.default(context.applicationContext)
}
val controlsState = remember(map, navigationManager, minimapState, settingsRepository) {
DefaultNavigationControlsState(
map = map,
navigationManager = navigationManager,
minimapState = minimapState,
settingsRepository = settingsRepository,
)
}

DisposableEffect(controlsState) {
onDispose { controlsState.onCleared() }
}

NavigationControlsComposable(state = controlsState)
}

Если репозиторий задан, NavigationControlsComposable автоматически покажет кнопку настроек в дашборде навигации и откроет встроенный экран настроек по нажатию.

Пользовательский сценарий

Если вы планируете создать собственный экран настроек или диалоговое окно, передайте onSettingsClick в NavigationControlsComposable. В этом случае встроенный экран не откроется, и будет вызван ваша функция обратного вызова

NavigationControlsComposable(
state = controlsState,
onSettingsClick = { settingsVisible = true },
)

Также передайте репозиторий в DefaultNavigationControlsState, чтобы SDK применял динамические настройки. Видимость кнопки обеспечивает onSettingsClick: если передана функция обратного вызова, дашборд покажет кнопку настроек и вызовет эту функцию по нажатию.

Готовые макеты

Для реализации собственного сценария вы можете использовать готовые макеты SDK:

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

@Composable
fun CustomSettingsScreen(
settingsRepository: NavigationSettingsRepository,
onClose: () -> Unit,
) {
var screen by remember { mutableStateOf(SettingsScreen.Root) }
val soundViewModel = remember(settingsRepository) {
DefaultSoundSettingsViewModel(settingsRepository)
}
val voicesViewModel = remember(settingsRepository) {
DefaultVoicesScreenViewModel(settingsRepository)
}

DisposableEffect(soundViewModel, voicesViewModel) {
onDispose {
soundViewModel.onCleared()
voicesViewModel.onCleared()
}
}

Column {
Button(onClick = onClose) {
Text(text = "Close")
}

when (screen) {
SettingsScreen.Root -> RouteSettingsLayout(
settingsRepository = settingsRepository,
onNavigateToSoundSettings = { screen = SettingsScreen.Sound },
onNavigateToBicycle = { screen = SettingsScreen.Bicycle },
onNavigateToVoicesSettings = { screen = SettingsScreen.Voices },
)
SettingsScreen.Sound -> SoundSettingsLayout(
viewModel = soundViewModel,
onNavigateToVoices = { screen = SettingsScreen.Voices },
)
SettingsScreen.Voices -> VoicesLayout(state = voicesViewModel)
SettingsScreen.Bicycle -> BicycleRouteSettingsLayout(
settingsRepository = settingsRepository,
)
}
}
}

Если вы создаёте DefaultSoundSettingsViewModel или DefaultVoicesScreenViewModel самостоятельно, вызовите onCleared() при уничтожении экрана. При использовании готового экрана настроек через DefaultNavigationControlsState это делается автоматически.

Настройки поиска маршрута

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

Пример для автомобильного маршрута:

fun createRouteSearchOptions(
settingsRepository: NavigationSettingsRepository,
): RouteSearchOptions = RouteSearchOptions(
CarRouteSearchOptions(
avoidTollRoads = settingsRepository[Keys.CAR_AVOID_TOLL_ROADS],
avoidUnpavedRoads = settingsRepository[Keys.CAR_AVOID_UNPAVED_ROADS],
avoidFerries = settingsRepository[Keys.CAR_AVOID_FERRIES],
avoidLockedRoads = settingsRepository[Keys.CAR_AVOID_LOCKED_ROADS],
routeSearchType = settingsRepository[Keys.CAR_ROUTE_SEARCH_TYPE],
)
)

Аналогично можно читать ключи для пешеходных, велосипедных, грузовых и других маршрутов из Keys.

Скрытие секций

Чтобы скрыть части готового экрана настроек, RouteSettingsLayout или SoundSettingsLayout, используйте SectionVisibilityConfig.

val visibilityConfig = remember {
SectionVisibilityConfig(
hiddenSections = setOf(
SectionVisibilityConfig.SECTION_TRUCK,
SectionVisibilityConfig.SECTION_PUBLIC_TRANSPORT,
SectionVisibilityConfig.SECTION_OTHER_SOUNDS,
)
)
}

NavigationControlsComposable(
state = controlsState,
settingsSectionVisibility = visibilityConfig,
)

Доступные идентификаторы секций:

ИдентификаторСкрываемая секция
SECTION_GENERAL_ROUTEОбщие настройки маршрута
SECTION_CAR_ROUTEНастройки автомобильного маршрута
SECTION_CALLOUT_VISUALIZATIONВизуализация подсказок
SECTION_MAP_EVENTSСобытия на карте
SECTION_PASSED_ROUTEПройденный маршрут
SECTION_NAVIGATION_LINKSСсылки на вложенные экраны из основного экрана
SECTION_PEDESTRIANСекция настроек пешеходного маршрута или ссылка на них
SECTION_BICYCLEСекция настроек маршрута для велосипеда или ссылка на них
SECTION_SCOOTERСекция настроек маршрута для самоката или ссылка на них
SECTION_MOTORCYCLEСекция настроек маршрута для мотоцикла или ссылка на них
SECTION_PUBLIC_TRANSPORTСекция настроек маршрута для общественного транспорта или ссылка на них
SECTION_TRUCKСекция настроек маршрута для грузового транспорта или ссылка на них
SECTION_SOUND_MASTERГлавный переключатель звукового режима
SECTION_EVENT_WARNINGSПредупреждения о событиях
SECTION_VOICESВыбор голосов озвучки
SECTION_OTHER_SOUNDSОстальные звуковые события

Тема

Вы можете использовать тему по умолчанию из NavigationSettingsTheme или переопределить отдельные параметры темы:

val theme = NavigationSettingsTheme.defaults(
colors = NavigationSettingsColors.colors().copy(
primary = Color(0xFF0A84FF),
)
)

RouteSettingsLayout(
settingsRepository = settingsRepository,
theme = theme,
)