0Pricing
Android Academy · Урок

Маркеры и камера

Размещайте маркеры и перемещайте камеру

«Маркеры и камера» — бесплатный урок Android Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Android Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Android Academy содержит 4 уроков всего.

Отметки на карте

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

В этом уроке вы добавите и настроите маркеры, объедините их в кластеры и плавно переместите камеру между местами.

Добавление маркера

В maps-compose маркеры — это компонуемые компоненты, которые размещаются внутри лямбды содержимого GoogleMap. Каждый Marker принимает MarkerState, хранящий его положение.

import com.google.maps.android.compose.Marker
import com.google.maps.android.compose.rememberMarkerState

@Composable
fun MapWithMarker() {
    val position = LatLng(37.7749, -122.4194)
    GoogleMap(modifier = Modifier.fillMaxSize()) {
        Marker(
            state = rememberMarkerState(position = position),
            title = "San Francisco",
            snippet = "Welcome to SF"
        )
    }
}

Заголовок, краткое описание и информационные окна

title и snippet отображаются в стандартном информационном окне, когда пользователь нажимает маркер. При нажатии заголовок отображается полужирным, а под ним — краткое описание.

Для полного контроля можно передать MarkerInfoWindow со своим содержимым компонуемого компонента.

Marker(
    state = rememberMarkerState(position = LatLng(48.8584, 2.2945)),
    title = "Eiffel Tower",
    snippet = "Paris, France",
    // The info window pops up on tap by default
)

Настройка значка маркера

Передайте BitmapDescriptor через параметр icon, чтобы изменить вид маркера. defaultMarker(hue) меняет цвет стандартной метки; также можно создать значок из ресурса изображения.

import com.google.android.gms.maps.model.BitmapDescriptorFactory

Marker(
    state = rememberMarkerState(position = LatLng(35.6895, 139.6917)),
    title = "Tokyo",
    icon = BitmapDescriptorFactory.defaultMarker(
        BitmapDescriptorFactory.HUE_AZURE
    )
)

Множество маркеров из данных

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

data class Place(val name: String, val latLng: LatLng)

@Composable
fun PlacesMap(places: List<Place>) {
    GoogleMap(modifier = Modifier.fillMaxSize()) {
        places.forEach { place ->
            Marker(
                state = rememberMarkerState(position = place.latLng),
                title = place.name
            )
        }
    }
}

Обработка нажатий на маркеры

Каждый Marker принимает лямбду onClick. Верните true, чтобы обработать событие (и подавить стандартное информационное окно), или false, чтобы разрешить стандартное поведение.

Marker(
    state = rememberMarkerState(position = LatLng(40.7128, -74.0060)),
    title = "New York",
    onClick = {
        // handle the tap, e.g. open a detail screen
        true // consume the event
    }
)

Мгновенное перемещение камеры

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

val cameraPositionState = rememberCameraPositionState()

// Instant move
cameraPositionState.position = CameraPosition.fromLatLngZoom(
    LatLng(51.5074, -0.1278), // London
    14f
)

Анимация камеры

Для более плавного взаимодействия анимируйте камеру с помощью animate(). Это приостанавливаемый вызов, поэтому запускайте его из области корутины. Используйте CameraUpdate, чтобы описать целевое положение.

import com.google.android.gms.maps.CameraUpdateFactory

val scope = rememberCoroutineScope()
Button(onClick = {
    scope.launch {
        cameraPositionState.animate(
            CameraUpdateFactory.newLatLngZoom(
                LatLng(48.8566, 2.3522), 13f
            ),
            durationMs = 1000
        )
    }
}) { Text("Fly to Paris") }

Отображение нескольких маркеров

Чтобы одновременно показать несколько маркеров, создайте LatLngBounds, содержащий их все, а затем выполните анимацию к этой области с помощью newLatLngBounds и отступа в пикселях.

import com.google.android.gms.maps.model.LatLngBounds

val bounds = LatLngBounds.Builder().apply {
    places.forEach { include(it.latLng) }
}.build()

scope.launch {
    cameraPositionState.animate(
        CameraUpdateFactory.newLatLngBounds(bounds, 100) // 100px padding
    )
}

Кластеризация множества маркеров

Сотни маркеров перегружают карту. Библиотека maps-compose-utils предоставляет Clustering, который объединяет близлежащие маркеры в один круг, разделяющийся при увеличении масштаба.

import com.google.maps.android.compose.clustering.Clustering

@Composable
fun ClusteredMap(items: List<MyClusterItem>) {
    GoogleMap(modifier = Modifier.fillMaxSize()) {
        Clustering(items = items)
    }
}

Чтение состояния камеры

Состояние камеры можно также читать. cameraPositionState.position содержит текущую целевую точку и масштаб, а isMoving сообщает, перемещает ли пользователь карту в данный момент. Это удобно, чтобы загружать данные только для видимой области по мере необходимости.

LaunchedEffect(cameraPositionState.isMoving) {
    if (!cameraPositionState.isMoving) {
        val center = cameraPositionState.position.target
        // fetch data near `center`
    }
}

Быстрая проверка

Вы хотите, чтобы камера плавно переместилась к новому месту за одну секунду, а не прыгнула туда мгновенно. Какой вариант правильный?

Итоги

Теперь вы умеете делать карту информативной и динамичной:

  • Размещайте компонуемые компоненты Marker внутри содержимого GoogleMap, задавая title, snippet и пользовательский icon.
  • Создавайте маркеры из списка данных и обрабатывайте onClick.
  • Перемещайте камеру мгновенно через position или плавно через animate().
  • Размещайте множество точек в видимой области с помощью LatLngBounds и уменьшайте загромождённость с помощью Clustering.

Далее: правильный запрос разрешений на местоположение, чтобы всё это работало на реальных устройствах.

Часто задаваемые вопросы

Урок «Маркеры и камера» бесплатный?

Да — полный текст урока «Маркеры и камера» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Android Academy, подпишись на CoddyKit PRO. Курс Android Academy содержит 4 уроков всего.

Чему я научусь в уроке «Маркеры и камера»?

Размещайте маркеры и перемещайте камеру Ты практикуешь Android Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Android Academy?

Предыдущий опыт не требуется. Android Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Маркеры и камера»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Android Academy?

Да. Каждый урок Android Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Отображение карты
  2. Получение местоположения пользователя
  3. Маркеры и камера
  4. Правильная работа с разрешениями на доступ к местоположению
← Назад к Android Academy