В статье мы поговорим о том, как интегрировать карты в приложение Jetpack Compose. Для этой цели потребуется библиотека Maps Compose.
Согласно официальной документации, библиотека Maps Compose содержит компонуемые функции и типы данных, позволяющие выполнять множество типовых задач.
Шаг 1. Получаем ключ API, следуя инструкциям по ссылке.
Шаг 2. Включаем требуемые зависимости:
implementation 'com.google.maps.android:maps-compose:2.7.2'
implementation 'com.google.android.gms:play-services-maps:18.1.0'
Примечание. Следует проверить, существует ли новые версии этих зависимостей.
Шаг 3. Добавляем метаданные в файл манифеста:
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${MAPS_API_KEY}" />
Все готово для реализации карт в коде!
Интеграция карт в приложение
Мы планируем показывать карты в приложении, вызывая GoogleMap()
. Вот такое простое решение! GoogleMap
— это компонуемый контейнер для MapView
, позволяющий отображать карты в приложении. Мы можем передавать множество параметров в функцию GoogleMap()
, но все они необязательные.
Перечислим некоторые из параметров.
cameraPositionState: CameraPositionState
используется для управления состоянием камеры карты и наблюдения за ним.googleMapOptionsFactory: () -> GoogleMapOptions
— блок для созданияGoogleMapOptions
, предоставляемых при создании карты.properties: MapProperties
— свойства карты, напримерisBuildingEnabled
,isIndoorEnabled
,isMyLocationEnabled
и т.д. ЕслиisMyLocationEnabled
установлено в значениеtrue
, то необходимо запросить разрешение для определения точного и приближенного местоположения.uiSettings: MapUiSettings
— настройки UI на карте, а именноcompassEnabled
,scrollGesturesEnabled
,rotationGesturesEnabled
и т.д.- Различные лямбда-функции, например
onMapClicked
,onMapLoaded
иonMyLocationButtonClick
.
Мы можем настроить состояние камеры для увеличения масштаба определенного местоположения:
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(LatLng(44.810058, 20.4617586), 16f)
}
Кроме того, предоставляется возможность получить последнее или текущее местоположение. Более подробная информация по этому вопросу представлена в следующей документации.
Маркеры
Представим, что нам нужно отметить на карте места, например ближайшие заправки и гостиницы. Для таких случаев библиотека предоставляет Markers
.
Компонуемая функция Marker
имеет несколько параметров. Здесь мы рассмотрим наиболее часто встречающиеся, но в дальнейшем желательно ознакомиться со всеми из них.
state: MarkerState
используется для управления состоянием маркера и наблюдения за ним, например его положением и информационным окном.draggable: Boolean
устанавливает способность перемещения маркера.flat: Boolean
определяет, должен ли маркер быть плоским по отношению к карте.icon: BitmapDescriptor
устанавливает значок для маркера.- Различные лямбда-функции, например
onClick
,onInfoWindowClick
,onInfoWindowClose
иonInfoWindowLongClick
.
Добавляем несколько маркеров разных цветов. Пример кода:
@Composable
fun GoogleMarkers() {
Marker(
state = rememberMarkerState(position = LatLng(44.811058, 20.4617586)),
title = "Marker1",
icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)
)
Marker(
state = rememberMarkerState(position = LatLng(44.811058, 20.4627586)),
title = "Marker2",
icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE)
)
Marker(
state = rememberMarkerState(position = LatLng(44.810058, 20.4627586)),
title = "Marker3",
icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW)
)
Marker(
state = rememberMarkerState(position = LatLng(44.809058, 20.4627586)),
title = "Marker4",
icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)
)
Marker(
state = rememberMarkerState(position = LatLng(44.809058, 20.4617586)),
title = "Marker5",
icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN)
)
}
Получить значок маркера можно из актива (англ. asset), ресурса, растрового изображения, файла и т.д. При нажатии на любой из маркеров появляется информационное окно с его названием.
Полилинии
Предположим, что нужно нарисовать линию между точками. Эта задача решается с помощью компонуемой функции Polyline
.
У нее только один обязательный параметр, а именно список значений широты и долготы. Перечислим ряд других параметров:
clickable: Boolean
— логическое значение. Оно показывает, активируется ли полилиния нажатием.color: Color
— цвет полилинии.startCap: Cap
— начальная верхняя точка полилинии.endCap: Cap
— конечная нижняя точка полилинии.width: Float
— ширина полилинии в пикселях экрана.onClick: (Polyline) -> Unit
— лямбда, вызываемая при нажатии полилинии.
Добавляем одну Polyline
для соединения маркеров:
Polyline(
points = listOf(
LatLng(44.811058, 20.4617586),
LatLng(44.811058, 20.4627586),
LatLng(44.810058, 20.4627586),
LatLng(44.809058, 20.4627586),
LatLng(44.809058, 20.4617586)
)
)
Итоговый вариант кода выглядит так:
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun MainScreen() {
val multiplePermissionState = rememberMultiplePermissionsState(
permissions = listOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(LatLng(44.810058, 20.4617586), 17f)
}
LaunchedEffect(Unit) {
multiplePermissionState.launchMultiplePermissionRequest()
}
MediumReposTheme {
Column(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colors.background)
.padding(16.dp)
) {
Text(
text = "Welcome to the MapsApp!",
style = MaterialTheme.typography.h5,
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(32.dp))
PermissionsRequired(
multiplePermissionsState = multiplePermissionState,
permissionsNotGrantedContent = { /* ... */ },
permissionsNotAvailableContent = { /* ... */ }
) {
GoogleMap(
cameraPositionState = cameraPositionState,
modifier = Modifier.weight(1f),
properties = MapProperties(isMyLocationEnabled = true),
uiSettings = MapUiSettings(compassEnabled = true)
) {
GoogleMarkers()
Polyline(
points = listOf(
LatLng(44.811058, 20.4617586),
LatLng(44.811058, 20.4627586),
LatLng(44.810058, 20.4627586),
LatLng(44.809058, 20.4627586),
LatLng(44.809058, 20.4617586)
)
)
}
}
}
}
}
@Composable
fun GoogleMarkers() {
Marker(
state = rememberMarkerState(position = LatLng(44.811058, 20.4617586)),
title = "Marker1",
icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)
)
Marker(
state = rememberMarkerState(position = LatLng(44.811058, 20.4627586)),
title = "Marker2",
icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE)
)
Marker(
state = rememberMarkerState(position = LatLng(44.810058, 20.4627586)),
title = "Marker3",
icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW)
)
Marker(
state = rememberMarkerState(position = LatLng(44.809058, 20.4627586)),
title = "Marker4",
icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)
)
Marker(
state = rememberMarkerState(position = LatLng(44.809058, 20.4617586)),
title = "Marker5",
icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN)
)
}
Для работы с картами существует много разных параметров и компонуемых функций, но в рамках данной статьи мы их рассматривать не будем. Все они подробно описаны в официальной документации, с которой вы можете ознакомиться.
На этом завершаем разговор о MapsApp
. Полный вариант исходного кода предоставлен в репозитории GitHub.
Читайте также:
- Как оптимизировать навигацию в Jetpack Compose
- Dynamic Feature Modules: навигация
- Введение в Navigation Architecture Component
Читайте нас в Telegram, VK и Дзен
Перевод статьи Igor Stevanovic: Integrate Google Maps Into the Jetpack Compose App