Компонент «Маркеры мест»

Компонент «Маркеры мест» позволяет создавать настраиваемые аннотации на карте, отображающие ключевую информацию о местах непосредственно на карте. Вы можете отображать такую ​​информацию, как рейтинг места, тип места, статус открытия или закрытия, ценовой диапазон или пользовательский текст (например, метку, сгенерированную ИИ, или номер маршрута). Это обеспечивает пользователям более информативный опыт изучения карты без необходимости переходить к подробной карточке места.

Доступные значки и текст для маркеров мест.

Для каждого PlaceMarker можно отобразить один значок маркера и, при необходимости, текст маркера.

Доступные значки:

  • Type : Тип места.
  • None : Нет значка.
Доступные текстовые маркеры:
  • Rating : Оценка.
  • PriceRange : Диапазон цен (например, 10-20 долларов).
  • OpenStatus : Информация о том, открыто или закрыто предприятие.
  • Custom : пользовательский текст (например, "ПОПУЛЯРНЫЙ").

Укажите местоположение, используя идентификатор места ( PlaceId ), название ресурса ( ResourceName ) или географические координаты ( Coordinates ).

Требования к отображению и указанию авторства

При отображении маркеров на карте из Places UI Kit, они не должны отображаться изолированно. Они должны быть интерактивными и при щелчке открывать связанный компонент с подробной информацией о месте или всплывающее окно, чтобы обеспечить необходимую фирменную символику Google, указание авторства и возможность сообщить о проблеме.

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

Примеры указателей мест

Мы предоставляем функции Jetpack Compose @Composable , чтобы исключить накладные расходы на обертку View-to-Compose и избежать проблем с несоответствием тем оформления.

Основные настройки маркеров

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

Котлин

import androidx.compose.runtime.Composable
import com.google.android.libraries.places.compose.PlaceMarker
import com.google.android.libraries.places.compose.marker.MarkerIcon
import com.google.android.libraries.places.compose.marker.MarkerText
import com.google.android.libraries.places.compose.PlaceReference

@Composable
fun DefaultMarker() {
    PlaceMarker(
        reference = PlaceReference.PlaceId("PLACE_ID"),
        icon = MarkerIcon.None,
        beakPresence = false, // remove beak
    )
}

@Composable
fun RatingMarker() {
    PlaceMarker(
        reference = PlaceReference.PlaceId("PLACE_ID"),
        icon = MarkerIcon.None,
        text = MarkerText.Rating
    )
}

@Composable
fun TypeAndRatingMarker() {
    PlaceMarker(
        reference = PlaceReference.PlaceId("PLACE_ID"),
        icon = MarkerIcon.Type,
        text = MarkerText.Rating

    )
}

@Composable
fun PriceRangeMarker() {
    PlaceMarker(
        reference = PlaceReference.ResourceName("places/PLACE_RESOURCE_NAME"),
        icon = MarkerIcon.None,
        text = MarkerText.PriceRange
    )
}

@Composable
fun OpenStatusMarker() {
   PlaceMarker(
       reference = PlaceReference.Coordinates(latitude = 37.7749, longitude = -122.4194),
        icon = MarkerIcon.None,
        text = MarkerText.OpenStatus
   )
}

@Composable
fun CustomTextMarker() {
    PlaceMarker(
        reference = PlaceReference.PlaceId("PLACE_ID"),
        icon = MarkerIcon.None,
        // Custom text accepts a String to display a number (e.g. "3") or text (e.g. "NEW")
        text = MarkerText.Custom("NEW")
    )
}

Создайте обработчик кликов.

Вы можете указать обработчик onClick для запуска пользовательских действий при нажатии на отдельный маркер. Однако, когда маркер отображается на карте (например, внутри MarkerComposable ), события нажатия перехватываются картой. В этом случае необходимо использовать обработчик onClick объекта MarkerComposable , а не самого маркера.

В следующем примере кода показано, как использовать обработчик onClick класса MarkerComposable .

Котлин

import android.util.Log
import androidx.compose.runtime.Composable
import com.google.android.libraries.places.compose.PlaceMarker
import com.google.android.libraries.places.compose.marker.MarkerIcon
import com.google.android.libraries.places.compose.PlaceReference


/**
 * PlaceMarker used outside of a map (e.g. in a list, bottom sheet, or custom overlay).
 *
 * There is no host component that provides a default click behavior here, so PlaceMarker's own
 * `onClick` is the only way for a developer to react to a tap. This is why `onClick` must stay
 * on the PlaceMarker API.
 */
@Composable
fun ClickableMarkerWithCustomConfig() {
   PlaceMarker(
       reference = PlaceReference.PlaceId("PLACE_ID"),
       icon = MarkerIcon.Type,
       
       onClick = { place ->
           openPlaceCard(place.id) // developer might want to open the place card
           Log.i("PlacesMarker", "Marker was tapped by user!")
       }
   )
}

/**
 * PlaceMarker used as the content of a MarkerComposable on a GoogleMap.
 *
 * MarkerComposable does NOT add PlaceMarker to the touch-input hierarchy: it snapshots the
 * composable into a bitmap and hands that bitmap to the Maps renderer as the marker icon. The
 * rendered marker is a map object, not a Compose node, so:
 *
 *   - PlaceMarker's own `onClick` would never be invoked here (no touch events ever reach it).
 *   - The tap is delivered by the Maps SDK to MarkerComposable's `onClick`, which is the only
 *     click entry point on a map.
 *
 * Accordingly, the state-based `PlaceMarker(state = ...)` overload used below deliberately does
 * not expose an `onClick` parameter, so the correct handler is the only one available.
 */
@Composable
fun PlaceMarkerOnMap(markerState: PlaceMarkerState) {
  GoogleMap(
    modifier = Modifier.fillMaxSize(),
    cameraPositionState = rememberCameraPositionState(),
  ) {
    markerState.location?.let { position ->
      MarkerComposable(
        state = rememberUpdatedMarkerState(position = position),
        // this is the click handler for the map use case.
        onClick = {
          markerState.place?.let { place -> openPlaceCard(place.id) }
          true // consume the event
        },
      ) {
        PlaceMarker(state = markerState)
      }
    }
  }
}

Обработка статуса загрузки и обратных вызовов.

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

Котлин

import android.util.Log
import androidx.compose.runtime.Composable
import com.google.android.libraries.places.compose.PlaceMarker
import com.google.android.libraries.places.compose.marker.MarkerIcon
import com.google.android.libraries.places.compose.PlaceReference

@Composable
fun StatusHandlingMarker() {
    PlaceMarker(
        reference = PlaceReference.PlaceId("PLACE_ID"),
        icon = MarkerIcon.Type,
        // Triggered when attribute data is successfully fetched and the marker is rendered.
        // Returns a minimal Place object with ID, location (LatLng), and viewport fields set.
        onMarkerLoaded = { place ->
            Log.i("PlacesMarker", "Marker successfully loaded for place ID: ${place.id}")
        },
        // Triggered when data fetching fails or required attribute data is missing for the place.
        // Returns an optional Place object and an Exception describing the root cause.
        onMarkerLoadFailed = { place, exception ->
            Log.e("PlacesMarker", "Failed to load marker for place ID: ${place?.id}", exception)
        }
    )
}

Используйте PlaceMarkerState для размещения маркеров на карте.

Объект Place возвращает местоположение и область просмотра, чтобы помочь вам определить, где разместить маркер.

Котлин

// Step 1: Obtain configured handle in a single 1-line call (PlaceMarker mounted internally)
val markerState = rememberPlaceMarkerState(
  reference = PlaceReference.PlaceId(placeId),
  icon = MarkerIcon.Type
)

// Step 2: Pass PlaceMarkerState.location and PlaceMarker(state = PlaceMarkerState) directly to the map marker
GoogleMap(...) {
  markerState.location?.let { position ->
    MarkerComposable(
      state = rememberMarkerState(position = position),
      onClick = {
        markerState.place?.let { place ->
          // Handle marker click
        }
        true
      }
    ) {
      PlaceMarker(state = markerState) // Render marker UI content directly on map canvas
    }
  }
}

Маркер шкалы нестандартного размера

Котлин

// Off the map: scale with a one-line modifier.
// Modifier.scale is a draw-time transform, so the bubble, beak, icon and text all scale together.
@Composable
fun ScaledMarker() {
  PlaceMarker(
    reference = PlaceReference.PlaceId(placeId),
    icon = MarkerIcon.Type,
    text = MarkerText.Rating,
    modifier = Modifier.scale(2.1f),
  )
}

// On the map: scale by overriding LocalDensity.
// MarkerComposable snapshots its content into a marker bitmap sized to the measured layout bounds.
// Modifier.scale does not change those bounds, so the marker would be clipped and blurry. Scaling
// the density re-measures every dp and sp inside the marker, so the bitmap, the layout bounds and
// the map hit target all grow with it.
@Composable
fun ScaledMarkerOnMap(markerState: PlaceMarkerState) {
  val density = LocalDensity.current
  val scaledDensity = remember(density) {
    Density(density = density.density * 2.1f, fontScale = density.fontScale * 2.1f)
  }
  GoogleMap(...) {
    markerState.location?.let { position ->
      MarkerComposable(
        state = rememberUpdatedMarkerState(position = position),
        anchor = Offset(0.5f, 1.0f),
      ) {
        CompositionLocalProvider(LocalDensity provides scaledDensity) {
          PlaceMarker(state = markerState)
        }
      }
    }
  }
}