Znaczniki

Wybierz platformę: Android iOS JavaScript

Znaczniki wskazują pojedyncze lokalizacje na mapie. Możesz dostosować znaczniki, zmieniając domyślny kolor lub zastępując ikonę niestandardowym obrazem. Okna z informacjami mogą zawierać dodatkowy kontekst dotyczący znacznika.

Przykładowe fragmenty kodu

Repozytorium ApiDemos na GitHubie zawiera przykład, który demonstruje różne funkcje znacznika:

Kotlin

Java

Wprowadzenie

Znaczniki wskazują miejsca na mapie. Domyślny znacznik używa standardowego ikony, która jest wspólna dla wyglądu i stylu Map Google. Za pomocą interfejsu API możesz zmienić kolor, obraz lub punkt kotwiczenia ikony. Znaki są obiektami typu Marker i są dodawane do mapy za pomocą metody GoogleMap.addMarker(markerOptions).

znaczniki są interaktywne; Domyślnie otrzymują one zdarzenia click i są często używane z detektorami zdarzeń do wyświetlania okien informacji. Ustawienie właściwości draggable na true pozwala użytkownikowi zmienić pozycję znacznika. Aby aktywować możliwość przeciągania znacznika, naciśnij i przytrzymaj.

Domyślnie, gdy użytkownik kliknie znacznik, w prawym dolnym rogu mapy pojawi się pasek narzędzi mapy, który umożliwia szybki dostęp do aplikacji mobilnej Mapy Google. Pasek narzędzi możesz wyłączyć. Więcej informacji znajdziesz w przewodniku po elementach sterujących.

Pierwsze kroki ze znacznikami

W tym odcinku Maps Live omawiamy podstawy dodawania znaczników do mapy za pomocą pakietu Maps SDK na Androida.

Dodaj znacznik

Ten przykład pokazuje, jak dodać znacznik do mapy. Znacznik jest tworzony na współrzędnych -33.852,151.211 (Sydney, Australia) i po kliknięciu wyświetla w oknie informacyjnym ciąg znaków „Znacznik w Sydney”.

Kotlin

override fun onMapReady(googleMap: GoogleMap) {
    // Add a marker in Sydney, Australia,
    // and move the map's camera to the same location.
    val sydney = LatLng(-33.852, 151.211)
    googleMap.addMarker(
        MarkerOptions()
            .position(sydney)
            .title("Marker in Sydney")
    )
    googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
}

      

Java

@Override
public void onMapReady(GoogleMap googleMap) {
    // Add a marker in Sydney, Australia,
    // and move the map's camera to the same location.
    LatLng sydney = new LatLng(-33.852, 151.211);
    googleMap.addMarker(new MarkerOptions()
        .position(sydney)
        .title("Marker in Sydney"));
    googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}

      

Wyświetlanie dodatkowych informacji o oznaczniku

Typowym wymaganiem jest wyświetlanie dodatkowych informacji o miejscu lub lokalizacji po kliknięciu przez użytkownika znacznika na mapie. Zapoznaj się z przeglądaniem okien informacyjnych.

Powiązanie danych ze znacznikiem

Możesz przechowywać dowolny obiekt danych z markerem za pomocą funkcji Marker.setTag(), a odzyskiwać obiekt danych za pomocą funkcji Marker.getTag(). Przykład poniżej pokazuje, jak za pomocą tagów zliczać liczbę kliknięć znacznika:

Kotlin

/**
 * A demo class that stores and retrieves data objects with each marker.
 */
class MarkerDemoActivity : AppCompatActivity(),
    OnMarkerClickListener, OnMapReadyCallback {
    private val PERTH = LatLng(-31.952854, 115.857342)
    private val SYDNEY = LatLng(-33.87365, 151.20689)
    private val BRISBANE = LatLng(-27.47093, 153.0235)

    private var markerPerth: Marker? = null
    private var markerSydney: Marker? = null
    private var markerBrisbane: Marker? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_markers)
        val mapFragment =
            supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
        mapFragment!!.getMapAsync(this)
    }

    /** Called when the map is ready.  */
    override fun onMapReady(map: GoogleMap) {
        // Add some markers to the map, and add a data object to each marker.
        markerPerth = map.addMarker(
            MarkerOptions()
                .position(PERTH)
                .title("Perth")
        )
        markerPerth?.tag = 0
        markerSydney = map.addMarker(
            MarkerOptions()
                .position(SYDNEY)
                .title("Sydney")
        )
        markerSydney?.tag = 0
        markerBrisbane = map.addMarker(
            MarkerOptions()
                .position(BRISBANE)
                .title("Brisbane")
        )
        markerBrisbane?.tag = 0

        // Set a listener for marker click.
        map.setOnMarkerClickListener(this)
    }

    /** Called when the user clicks a marker.  */
    override fun onMarkerClick(marker: Marker): Boolean {

        // Retrieve the data from the marker.
        val clickCount = marker.tag as? Int

        // Check if a click count was set, then display the click count.
        clickCount?.let {
            val newClickCount = it + 1
            marker.tag = newClickCount
            Toast.makeText(
                this,
                "${marker.title} has been clicked $newClickCount times.",
                Toast.LENGTH_SHORT
            ).show()
        }

        // Return false to indicate that we have not consumed the event and that we wish
        // for the default behavior to occur (which is for the camera to move such that the
        // marker is centered and for the marker's info window to open, if it has one).
        return false
    }
}

      

Java

/**
 * A demo class that stores and retrieves data objects with each marker.
 */
public class MarkerDemoActivity extends AppCompatActivity implements
    GoogleMap.OnMarkerClickListener,
    OnMapReadyCallback {

    private final LatLng PERTH = new LatLng(-31.952854, 115.857342);
    private final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
    private final LatLng BRISBANE = new LatLng(-27.47093, 153.0235);

    private Marker markerPerth;
    private Marker markerSydney;
    private Marker markerBrisbane;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_markers);
        SupportMapFragment mapFragment =
            (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    /** Called when the map is ready. */
    @Override
    public void onMapReady(GoogleMap map) {
        // Add some markers to the map, and add a data object to each marker.
        markerPerth = map.addMarker(new MarkerOptions()
            .position(PERTH)
            .title("Perth"));
        markerPerth.setTag(0);

        markerSydney = map.addMarker(new MarkerOptions()
            .position(SYDNEY)
            .title("Sydney"));
        markerSydney.setTag(0);

        markerBrisbane = map.addMarker(new MarkerOptions()
            .position(BRISBANE)
            .title("Brisbane"));
        markerBrisbane.setTag(0);

        // Set a listener for marker click.
        map.setOnMarkerClickListener(this);
    }

    /** Called when the user clicks a marker. */
    @Override
    public boolean onMarkerClick(final Marker marker) {

        // Retrieve the data from the marker.
        Integer clickCount = (Integer) marker.getTag();

        // Check if a click count was set, then display the click count.
        if (clickCount != null) {
            clickCount = clickCount + 1;
            marker.setTag(clickCount);
            Toast.makeText(this,
                marker.getTitle() +
                    " has been clicked " + clickCount + " times.",
                Toast.LENGTH_SHORT).show();
        }

        // Return false to indicate that we have not consumed the event and that we wish
        // for the default behavior to occur (which is for the camera to move such that the
        // marker is centered and for the marker's info window to open, if it has one).
        return false;
    }
}

      

Oto kilka przykładów sytuacji, w których przydatne jest przechowywanie i pobieranie danych za pomocą znaczników:

  • Twoja aplikacja może obsługiwać różne typy znaczników i chcesz je traktować inaczej, gdy użytkownik kliknie jeden z nich. Aby to zrobić, możesz przechowywać wartość String z oznacznikiem wskazującym typ.
  • Możesz mieć do czynienia z systemem, który ma unikalne identyfikatory rekordów, gdzie znaczniki reprezentują konkretne rekordy w tym systemie.
  • Dane znacznika mogą wskazywać priorytet, który ma być używany przy określaniu indeksu z znacznika.

Ustawianie znacznika jako przeciąganego

Po dodaniu znacznika do mapy możesz zmienić jego położenie, o ile tylko właściwość draggable jest ustawiona na true. Naciśnij i przytrzymaj znacznik, aby umożliwić przeciąganie. Gdy odłączysz palec od ekranu, znacznik pozostanie w tej pozycji.

Domyślnie znaczniki nie są przeciągane. Musisz wyraźnie ustawić, że znacznik ma być przeciągany, albo za pomocą MarkerOptions.draggable(boolean) przed dodaniem go do mapy, albo za pomocą Marker.setDraggable(boolean) po dodaniu go do mapy. Możesz nasłuchiwać zdarzeń przeciągania znacznika, jak opisano w sekcji Zdarzenia przeciągania znacznika.

Poniższy fragment kodu dodaje przeciągany znacznik do Perth w Australii.

Kotlin

val perthLocation = LatLng(-31.90, 115.86)
val perth = map.addMarker(
    MarkerOptions()
        .position(perthLocation)
        .draggable(true)
)

      

Java

final LatLng perthLocation = new LatLng(-31.90, 115.86);
Marker perth = map.addMarker(
    new MarkerOptions()
        .position(perthLocation)
        .draggable(true));

      

Dostosowywanie znacznika

Ten film pokazuje sposoby wizualizacji lokalizacji na mapie za pomocą znaczników.

Markery mogą zawierać niestandardowy obraz, który będzie wyświetlany zamiast domyślnej ikony. Definiowanie ikony wymaga ustawienia kilku właściwości, które wpływają na zachowanie wizualne znacznika.

Znaczniki obsługują dostosowywanie za pomocą tych właściwości:

Pozycja (wymagana)
Wartość LatLng dla położenia znacznika na mapie. Jest to jedyna wymagana właściwość obiektu Marker.
Kotwica
Punkt na obrazie, który zostanie umieszczony w pozycji LatLng znacznika. Domyślnie jest to środek dołu obrazu.
Alfa
Ustawia przezroczystość znacznika. Domyślna wartość to 1,0.
Tytuł
Ciąg tekstowy wyświetlany w oknie informacyjnym po kliknięciu przez użytkownika znacznika.
Krótki opis
Dodatkowy tekst wyświetlany pod tytułem.
Ikona
Plik mapy bitowej wyświetlany zamiast domyślnego obrazu znacznika.
Przeciąganie
Ustaw na true, jeśli chcesz zezwolić użytkownikowi na przenoszenie znacznika. Domyślna wartość to false.
Widoczne
Ustaw na false, aby ukryć znacznik. Domyślna wartość to true.
Orientacja pozioma lub pionowa
Domyślnie znaczniki mają orientację billboardową, co oznacza, że są one wyświetlane na ekranie urządzenia, a nie na powierzchni mapy. Obracanie, przechylanie i powiększanie mapy nie zmienia orientacji znacznika. Możesz ustawić orientację znacznika tak, aby był płaski na powierzchni Ziemi. Płaskie znaczniki obracają się, gdy obracasz mapę, i zmieniają perspektywę, gdy ją przechylisz. Podobnie jak w przypadku znaczników typu billboard, znaczniki płaskie zachowują swój rozmiar podczas powiększania lub pomniejszania mapy.
Obrót
Orientacja znacznika określona w stopniach w kierunku ruchu wskazówek zegara. Domyślna pozycja zmienia się, jeśli znacznik jest płaski. Domyślna pozycja płaskiego znacznika to kierunek na północ. Gdy znacznik nie jest płaski, jego domyślna pozycja jest skierowana w górę, a obrócenie jest takie, że znacznik jest zawsze skierowany w kierunku kamery.

Podany niżej fragment kodu tworzy prosty znacznik z domyślną ikoną.

Kotlin

val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
)

      

Java

final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(
    new MarkerOptions()
        .position(melbourneLocation));

      

Dostosowywanie koloru znacznika

Kolor obrazu znacznika domyślnego można dostosować, przekazując do metody icon() obiekt BitmapDescriptor. Możesz użyć zestawu wstępnie zdefiniowanych kolorów w obiekcie BitmapDescriptorFactory lub ustawić niestandardowy kolor znacznika za pomocą metody BitmapDescriptorFactory.defaultMarker(float hue). Barwa to wartość z zakresu 0–360, która reprezentuje punkty na kole kolorów.

Kotlin

val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
)

      

Java

final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(
    new MarkerOptions()
        .position(melbourneLocation)
        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));

      

Dostosowywanie przezroczystości znacznika

Za pomocą metody MarkerOptions.alpha() możesz kontrolować przezroczystość znacznika. Wartość alfa powinna być podana jako liczba zmiennoprzecinkowa z zakresu od 0,0 do 1,0, gdzie 0 oznacza całkowitą przezroczystość, a 1 – całkowity brak przezroczystości.

Kotlin

val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
        .alpha(0.7f)
)

      

Java

final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(new MarkerOptions()
    .position(melbourneLocation)
    .alpha(0.7f));

      

Dostosowywanie obrazu znacznika

Możesz zastąpić domyślny obraz znacznika niestandardowym obrazem znacznika, który często nazywany jest ikoną. Ikony niestandardowe są zawsze ustawiane jako BitmapDescriptor i definiowane za pomocą jednej z metod w klasie BitmapDescriptorFactory.

fromAsset(String assetName)
Tworzy znacznik niestandardowy za pomocą nazwy obrazu typu Bitmap w katalogu Assets.
fromBitmap(Bitmap image)
Tworzy niestandardowy znacznik na podstawie obrazu bitmapowego.
fromFile(String fileName)
Tworzy ikonę niestandardową na podstawie nazwy pliku obrazu typu Bitmap znajdującego się w pamięci wewnętrznej.
fromPath(String absolutePath)
Tworzy znacznik niestandardowy na podstawie bezwzględnej ścieżki do pliku obrazu typu Bitmap.
fromResource(int resourceId)
Tworzy znacznik niestandardowy za pomocą identyfikatora zasobu obrazu typu Bitmap.

Poniżej znajduje się fragment kodu, który tworzy znacznik z niestandardową ikoną.

Kotlin

val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
        .title("Melbourne")
        .snippet("Population: 4,137,400")
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow))
)

      

Java

final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(
    new MarkerOptions()
        .position(melbourneLocation)
        .title("Melbourne")
        .snippet("Population: 4,137,400")
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)));

      

Spłaszczanie znacznika

Ikony znaczników są zwykle wyświetlane względem ekranu. Obracanie, przechylanie lub powiększanie mapy nie zmienia orientacji znacznika. Możesz ustawić orientację znacznika tak, aby był płaski na Ziemi. Znaczniki o takim ułożeniu będą się obracać, gdy obróci się mapę, i zmieniać perspektywę, gdy ją przechyli. Płaskie znaczniki zachowują swój rozmiar podczas powiększania lub pomniejszania mapy.

Aby zmienić orientację znacznika, ustaw jego właściwość flat na true.

Kotlin

val perthLocation = LatLng(-31.90, 115.86)
val perth = map.addMarker(
    MarkerOptions()
        .position(perthLocation)
        .flat(true)
)

      

Java

final LatLng perthLocation = new LatLng(-31.90, 115.86);
Marker perth = map.addMarker(
    new MarkerOptions()
        .position(perthLocation)
        .flat(true));

      

Obracanie znacznika

Możesz obracać znacznik wokół punktu zakotwiczenia za pomocą przycisku Marker.setRotation() metody. Obrót jest mierzony w stopniach zgodnie z ruchem wskazówek zegara względem pozycji domyślnej. Gdy znacznik jest płaski na mapie, domyślną pozycją jest północ. Gdy znacznik nie jest płaski, jego domyślna pozycja jest skierowana w górę, a obrócenie jest takie, że znacznik jest zawsze skierowany w kierunku kamery.

W przykładzie poniżej znacznik jest obracany o 90°. Ustawienie punktu kotwiczenia na 0.5,0.5 powoduje, że znacznik jest obracany wokół swojego środka, a nie podstawy.

Kotlin

val perthLocation = LatLng(-31.90, 115.86)
val perth = map.addMarker(
    MarkerOptions()
        .position(perthLocation)
        .anchor(0.5f, 0.5f)
        .rotation(90.0f)
)

      

Java

final LatLng perthLocation = new LatLng(-31.90, 115.86);
Marker perth = map.addMarker(
    new MarkerOptions()
        .position(perthLocation)
        .anchor(0.5f,0.5f)
        .rotation(90.0f));

      

Z-index znacznika

Indeks Z określa kolejność nakładania tego znacznika względem innych znaczników na mapie. znacznik o wysokiej wartości wskaźnika z-index jest narysowany na wierzchu znaczników o niższej wartości tego wskaźnika; Wartością domyślną z-index jest 0.

Ustaw indeks Z obiektu opcji znacznika, wywołując funkcję MarkerOptions.zIndex(), jak pokazano w tym fragmencie kodu:

Kotlin

map.addMarker(
    MarkerOptions()
        .position(LatLng(10.0, 10.0))
        .title("Marker z1")
        .zIndex(1.0f)
)

      

Java

map.addMarker(new MarkerOptions()
    .position(new LatLng(10, 10))
    .title("Marker z1")
    .zIndex(1.0f));

      

Aby uzyskać dostęp do indeksu Z znacznika, wywołaj funkcję Marker.getZIndex(), a aby go zmienić, wywołaj funkcję Marker.setZIndex().

znaczniki są zawsze wyświetlane nad warstwami płytek i innymi nakładkami (nakładkami na grunt, poliliniami, wielokątami i innymi kształtami) niezależnie od z-indeksu innych nakładek. W porównaniu z innymi nakładkami znaczniki są traktowane jako należące do osobnej grupy indeksu Z.

Poniżej znajdziesz informacje o wpływie indeksu Z na zdarzenia kliknięcia.

Obsługa zdarzeń znacznika

Interfejs Maps API umożliwia nasłuchiwanie zdarzeń znacznika i reagowanie na nie. Aby nasłuchiwać te zdarzenia, musisz ustawić odpowiedni detektor w obiekcie GoogleMap, do którego należą znaczniki. Gdy zdarzenie wystąpi na jednym ze znaczników na mapie, zostanie wywołane wywołanie zwrotne detektora z odpowiednim obiektem Marker przekazanym jako parametr. Aby porównać ten obiekt Marker z własnym odwołaniem do obiektu Marker, musisz użyć equals(), a nie ==.

Możesz słuchać tych zdarzeń:

Zdarzenia kliknięcia znacznika

Możesz użyć tagu OnMarkerClickListener, aby nasłuchiwać zdarzeń kliknięcia na znaczniku. Aby ustawić tego słuchacza na mapie, wywołaj funkcję GoogleMap.setOnMarkerClickListener(OnMarkerClickListener). Gdy użytkownik kliknie znacznik, zostanie wywołana metoda onMarkerClick(Marker), a znacznik zostanie przekazany jako argument. Zwraca ona wartość logiczną wskazującą, czy zdarzenie zostało już wykorzystane (czyli czy chcesz zablokować domyślne zachowanie). Jeśli zwróci wartość false, działanie domyślne zostanie wykonane oprócz działania niestandardowego. Domyślne zachowanie zdarzenia kliknięcia znacznika polega na wyświetleniu okna z informacjami (jeśli jest dostępne) i przesunięciu kamery tak, aby znacznik znalazł się na środku mapy.

Wpływ indeksu Z na zdarzenia kliknięcia:

  • Gdy użytkownik kliknie grupę znaczników, zostanie wywołane zdarzenie kliknięcia dla znacznika o najwyższym indeksie z.
  • Na każde kliknięcie może być wywoływane maksymalnie 1 zdarzenie. Inaczej mówiąc, kliknięcie nie jest przekazywane do markerów ani innych nakładek o niższej wartości Kolejności nakładania elementów.
  • Kliknięcie grupy znaczników powoduje, że kolejne kliknięcia będą przełączać się między elementami w grupie. Kolejność cyklu jest ustalana według priorytetów: najpierw z-index, a potem odległość od punktu kliknięcia.
  • Jeśli użytkownik kliknie poza obszarem klastra, interfejs API ponownie obliczy klaster i zresetuje stan cyklu kliknięć, aby rozpoczął się od początku.
  • Zdarzenie kliknięcia przechodzi przez grupy znaczników do innych kształtów i nakładek, a potem uruchamia cykl od nowa.
  • W porównaniu z innymi nakładkami lub kształtami (polilinia, wielokąty, koła lub nakładki na grunt) znaczniki są traktowane jako należące do osobnej grupy indeksu z, niezależnie od indeksu z innych nakładek. Jeśli na siebie nakładają się liczne znaczniki, nakładki lub kształty, zdarzenie kliknięcia jest najpierw wywoływane przez grupę znaczników, a potem przez inne klikalne nakładki lub kształty na podstawie ich wartości indeksu Z.

zdarzenia przeciągania znacznika;

Możesz użyć OnMarkerDragListener, aby nasłuchiwać zdarzeń przeciągania znacznika. Aby ustawić tego słuchacza na mapie, wywołaj funkcję GoogleMap.setOnMarkerDragListener. Aby przeciągnąć znacznik, użytkownik musi nacisnąć go dłużej. Gdy użytkownik odsunie palec od ekranu, znacznik pozostanie w tej pozycji. Gdy przeciągasz znacznik, początkowo wywoływana jest funkcja onMarkerDragStart(Marker). Podczas przeciągania znacznika funkcja onMarkerDrag(Marker) jest stale wywoływana. Na końcu funkcji przeciągania wywoływana jest funkcja onMarkerDragEnd(Marker). Pozycję znacznika możesz uzyskać w dowolnym momencie, wywołując funkcję Marker.getPosition().