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

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 = "14.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) и позволяет изменять его.

  6. 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 для отображения информации в режиме ведения по маршруту.

     

  9. NavigationDashboardComposable для отображения информации в режиме свободной навигации.

  10. NavigationDashboardComposable для отображения информации в режиме навигации внутри зданий.

  11. NavigationIndoorComposable для управления списком этажей при навигации внутри здания.

      

  12. BetterRoutePromptComposable для отображения предложения о переходе на «маршрут лучше».

  13. FinishRouteComposable для отображения информации о завершении маршрута.

  14. RouteOverviewComposable для отображения общей информации о маршруте во время навигации.

      

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

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

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

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

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

@Composable
fun NavigationControls(
context: Context,
map: Map,
navigationManager: NavigationManager,
) {
val settingsRepository = remember(context) {
NavigationSettingsRepository.default(context.applicationContext)
}
val controlsState = remember(map, navigationManager, settingsRepository) {
DefaultNavigationControlsState(
map = map,
navigationManager = navigationManager,
minimapOptions = MapControllerOptions(),
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,
)