Znaczniki

Wybierz platformę: Android iOS JavaScript

Znaczniki wskazują pojedyncze lokalizacje na mapie. Możesz dostosować znaczniki, zmieniając kolor domyślny lub zamieniając ikonę znacznika na obraz niestandardowy. Okna informacyjne mogą dostarczyć znacznikowi dodatkowy kontekst.

Przykładowe fragmenty kodu

Repozytorium ApiDemos na GitHubie zawiera próbkę prezentującą różne funkcje znaczników:

Java

Kotlin

Wprowadzenie

Znaczniki wskazują lokalizacje na mapie. Domyślny znacznik jest używany standardową ikoną, która jest typowa dla wyglądu i sposobu działania Map Google. Kolor, obraz lub punkt zakotwiczenia można zmienić za pomocą interfejsu API. Znaczniki to obiekty typu Marker i są dodawane do mapy metodą GoogleMap.addMarker(markerOptions).

Znaczniki są zaprojektowane w sposób interaktywny. Domyślnie otrzymują zdarzenia click i często są używane przez detektory do wywoływania okna informacyjnego. Ustawienie właściwości draggable znacznika na true umożliwia użytkownikowi zmianę położenia znacznika. Przytrzymaj dłużej, aby aktywować możliwość przenoszenia znacznika.

Domyślnie, gdy użytkownik kliknie znacznik, w prawym dolnym rogu mapy pojawi się pasek narzędzi z mapą. Dzięki temu użytkownik uzyska szybki dostęp do aplikacji mobilnej Mapy Google. Możesz wyłączyć ten pasek. Więcej informacji znajdziesz w przewodniku po ustawieniach.

Pierwsze kroki ze znacznikami

Ten odcinek Map Live na żywo omawia podstawy dodawania znaczników do mapy za pomocą pakietu Maps SDK na Androida.

Dodaj znacznik

Poniższy przykład pokazuje, jak dodać znacznik do mapy. Znacznik jest tworzony w miejscu współrzędnych -33.852,151.211 (Sydney, Australia) i po kliknięciu wyświetla się tekst „Marker in 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));
}

      

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))
}

      

Wyświetl dodatkowe informacje na temat znacznika

Typowym wymaganiem jest wyświetlanie dodatkowych informacji o miejscu lub lokalizacji, gdy użytkownik kliknie znacznik na mapie. Zajrzyj do przewodnika po oknach informacyjnych.

Powiąż dane ze znacznikiem

Możesz przechowywać dowolny obiekt danych ze znacznikiem za pomocą Marker.setTag(), a obiekt obiektu danych pobierać za pomocą Marker.getTag(). Poniższy przykład pokazuje, jak możesz zliczać liczbę kliknięć znacznika za pomocą tagów:

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;
    }
}

      

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
    }
}

      

Oto kilka przykładów użycia pamięci do przechowywania i pobierania danych ze znacznikami:

  • Aplikacja może obsługiwać różne typy znaczników i chcesz, aby były traktowane inaczej w zależności od tego, kiedy użytkownik je kliknie. W tym celu możesz zapisać String ze znacznikiem określającym typ.
  • Być może wchodzisz w interakcję z systemem, który ma unikalne identyfikatory rekordów, gdzie znaczniki reprezentują określone rekordy w tym systemie.
  • Dane dotyczące znacznika mogą wskazywać, że ma on być używany podczas określania kolejności nakładania się elementów.

Przeciągnij znacznik

Możesz zmienić położenie znacznika po dodaniu go do mapy, o ile właściwość draggable jest ustawiona na true. Przytrzymaj znacznik, aby włączyć przeciąganie. Gdy zdejmiesz palec z ekranu, znacznik pozostanie w tym miejscu.

Znaczniki nie są domyślnie przeciągane. Przed dodaniem znacznika do mapy musisz wyraźnie ustawić go w taki sposób, aby można było go przesunąć MarkerOptions.draggable(boolean), lub po dodaniu go do mapy: Marker.setDraggable(boolean). Możesz śledzić zdarzenia przeciągania na znaczniku, tak jak to opisano w sekcji Zdarzenia typu „Marker przeciąganie”.

Fragment kodu poniżej zawiera przesuwany znacznik w Perth (Australia).

Java


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

      

Kotlin


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

      

Dostosuj znacznik

Ten film pokazuje, jak używać znaczników do wizualizacji lokalizacji na mapie.

Znaczniki mogą określać obrazy niestandardowe, które będą wyświetlane zamiast ikony domyślnej. Definicja ikony oznacza ustawienie szeregu właściwości, które mają wpływ na wygląd znacznika.

Znaczniki umożliwiają dostosowywanie za pomocą tych właściwości:

Pozycja (wymagana)
Pozycja LatLng znacznika na mapie. To jedyna wymagana właściwość obiektu Marker.
Kotwica
Punkt na obrazie, który zostanie umieszczony w pozycji długości geograficznej znacznika. Domyślnie znajduje się ona na środku u dołu obrazu.
Alfa
Ustaw przezroczystość znacznika. Domyślna wartość to 1.0.
Stanowisko
Ciąg, który pojawia się w oknie informacyjnym po kliknięciu znacznika przez użytkownika.
Fragment
Dodatkowy tekst wyświetlany pod tytułem.
Ikona
Mapa bitowa, która jest wyświetlana zamiast domyślnego znacznika.
Przeciągnij
Ustaw wartość true, jeśli chcesz zezwolić użytkownikowi na przenoszenie znacznika. Domyślna wartość to false.
Widoczne
Ustaw wartość false, aby znacznik był niewidoczny. Domyślna wartość to true.
Orientacja płaska lub Billboard
Domyślnie znaczniki są ustawione w orientacji billboardowej, co oznacza, że są kierowane względem ekranu urządzenia, a nie powierzchni mapy. Obracanie, pochylanie i powiększanie mapy nie powoduje zmiany orientacji znacznika. Możesz ustawić znacznik płasko na ziemi. Płaskie znaczniki są obracane, gdy mapa jest obrócona, a widok zmienia się po pochyleniu mapy. Tak jak w przypadku znaczników billboardów, płaskie znaczniki zachowują rozmiar po powiększeniu lub pomniejszeniu mapy.
Rotacja
Orientacja znacznika w stopniach zgodnie z ruchem wskazówek zegara. Pozycja domyślna zmienia się, jeśli znacznik jest płaski. Domyślna pozycja znacznika płaskiego jest wyrównana na północ. Gdy znacznik nie jest płaski, położenie domyślne jest skierowane w górę, a obrót odbywa się tak, że znacznik jest zawsze skierowany do aparatu.

Fragment kodu poniżej tworzy prosty znacznik z ikoną domyślną.

Java


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

      

Kotlin


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

      

Dostosuj kolor znacznika

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

Java


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

      

Kotlin


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

      

Dostosuj przezroczystość znacznika

Przezroczystość znacznika można kontrolować za pomocą metody MarkupOptions.alpha(). Wartość alfa powinna być liczbą zmiennoprzecinkową z zakresu od 0,0 do 1,0, gdzie 0 oznacza pełną przezroczystość, a 1 – pełną nieprzejrzystość.

Java


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

      

Kotlin


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

      

Dostosuj obraz znacznika

Domyślny obraz znacznika możesz zastąpić niestandardowym obrazem znacznika, często nazywanym ikoną. Ikony niestandardowe są zawsze ustawiane jako właściwość BitmapDescriptor i definiowanie przy użyciu jednej z metod w klasie BitmapDescriptorFactory.

fromAsset(String assetName)
Tworzy niestandardowy znacznik z nazwą obrazu bitmapy w katalogu zasobów.
fromBitmap(Bitmap image)
Tworzy niestandardowy znacznik z obrazu bitmapy.
fromFile(String fileName)
Tworzy ikonę niestandardową z nazwą pliku obrazu Bitmap znajdującego się w pamięci wewnętrznej.
fromPath(String absolutePath)
Tworzy niestandardowy znacznik z bezwzględnej ścieżki pliku obrazu Bitmap.
fromResource(int resourceId)
Tworzy niestandardowy znacznik z identyfikatorem zasobu obrazu Bitmap.

Fragment kodu poniżej tworzy znacznik z ikoną niestandardową.

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)));

      

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))
)

      

Spłaszcz znacznik

Ikony znacznika są zwykle rysowane w odniesieniu do ekranu. Obracanie, pochylanie i powiększanie mapy nie powoduje zmiany orientacji znacznika. Możesz ustawić znacznik płasko względem ziemi. Takie znaczniki są obracane po obróceniu mapy oraz zmieniają perspektywę po pochyleniu mapy. Płaskie znaczniki zachowają rozmiar po powiększeniu lub pomniejszeniu mapy.

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

Java


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

      

Kotlin


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

      

Obracanie znacznika

Znacznik możesz obracać wokół punktu zakotwiczenia za pomocą właściwości Marker.Metoda setRotation(). Obrót jest mierzony w stopniach w prawo od pozycji domyślnej. Kiedy znacznik jest płaski na mapie, domyślną pozycją jest północ. Gdy znacznik nie jest płaski, położenie domyślne jest skierowane w górę, a obrót powinien być zawsze skierowany w stronę aparatu.

W poniższym przykładzie znacznik jest obracany o 90°. Ustawienie punktu zakotwiczenia na wartość 0.5,0.5 powoduje, że znacznik będzie obracał się wokół jego środka, a nie jego podstawy.

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));

      

Kotlin


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

      

Kolejność nakładania elementów

Kolejność nakładania elementów określa kolejność stosu tego znacznika na tle innych znaczników na mapie. Znacznik o wysokim z-z jest rysowany nad znacznikami o niższym z-index. Domyślna wartość kolejności nakładania elementów to 0.

Ustaw kolejność nakładania elementów w obiekcie opcji znacznika, wywołując MarkerOptions.zIndex(), jak pokazano w tym fragmencie kodu:

Java


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

      

Kotlin


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

      

Aby uzyskać dostęp do kolejności nakładania elementów, przejdź do tagu Marker.getZIndex() i zmień go na Marker.setZIndex().

Znaczniki są zawsze rysowane nad warstwami płytek i innymi warstwami niebędącymi znacznikami (nakładki na powierzchni, linie łamane, wielokąty i inne kształty) niezależnie od kolejności nakładania się innych elementów. Znaczniki są właściwie uznawane za oddzielne grupy Z-index w porównaniu z innymi nakładkami.

Poniżej znajdziesz informacje o wpływie kolejności nakładania elementów na zdarzenia kliknięcia.

Obsługa zdarzeń znacznika

Interfejs API Map Google umożliwia słuchanie zdarzeń znacznika i reagowanie na nie. Aby nasłuchiwać tych zdarzeń, musisz ustawić odpowiedni detektor w obiekcie GoogleMap, do którego należą znaczniki. Gdy zdarzenie wystąpi na jednym ze znaczników na mapie, wywołanie zwrotne detektora będzie wywoływane z odpowiednim obiektem Marker przekazanym jako parametr. Aby porównać ten obiekt Marker z własnym odwołaniem do obiektu Marker, musisz użyć właściwości equals(), a nie ==.

Możesz odsłuchać te zdarzenia:

Zdarzenia kliknięcia znacznika

Za pomocą OnMarkerClickListener możesz wykrywać zdarzenia kliknięcia na znaczniku. Aby ustawić go na mapie, wywołaj funkcję GoogleMap.setOnMarkerClickListener(OnMarkerClickListener). Gdy użytkownik kliknie znacznik, zostanie wywołany element onMarkerClick(Marker), a znacznik zostanie przekazany jako argument. Ta metoda zwraca wartość logiczną, która określa, czy zdarzenie zostało wykorzystane (tj. czy chcesz pominąć domyślne zachowanie). Jeśli zwraca false, zachowanie niestandardowe będzie dodatkiem do zachowania niestandardowego. Domyślnym działaniem w przypadku zdarzenia kliknięcia znacznika jest wyświetlenie jego okna informacyjnego (jeśli jest dostępne) i przesunięcie kamery tak, aby znacznik wyśrodkował się na mapie.

Wpływ kolejności nakładania elementów na zdarzenia kliknięcia:

  • Gdy użytkownik kliknie klaster znaczników, zostanie wywołane zdarzenie kliknięcia w przypadku znacznika o najwyższym kolejności nakładania elementów.
  • Najczęściej wywoływane jest jedno zdarzenie na kliknięcie. Oznacza to, że kliknięcie nie jest przekazywane do znaczników ani innych nakładek, które mają niższą wartość kolejności nakładania elementów.
  • Kliknięcie klastra oznacza, że kolejne kliknięcia będą się powtarzać, Kolejność cyklu zaczyna się od priorytetu z-index, a potem odległości od punktu kliknięcia.
  • Jeśli użytkownik kliknie miejsce poza zasięgiem klastra, interfejs API ponownie przeliczy klaster i zresetuje stan cyklu kliknięcia, zanim zacznie się od początku.
  • Zdarzenie kliknięcia przechodzi przez klastry znaczników do innych kształtów i nakładek przed ponownym uruchomieniem cyklu.
  • Znaczniki są właściwie uznawane za oddzielne grupy Z-index w porównaniu z innymi nakładkami lub kształtami (linie, wielokąty, okręgi i/nakładki na powierzchni) niezależnie od kolejności nakładania się innych nakładanych elementów. Jeśli nałożonych jest na siebie wiele znaczników, nakładek lub kształtów, zdarzenie kliknięcia przechodzi przez kilka znaczników, a następnie uruchamia się je dla innych nakładek lub kształtów, które można kliknąć, w zależności od wartości ich kolejności nakładania się.

Zdarzenia przeciągania znacznika

Za pomocą OnMarkerDragListener możesz nasłuchiwać zdarzeń przeciągnięcia na znaczniku. Aby ustawić go na mapie, wywołaj funkcję GoogleMap.setOnMarkerDragListener. Aby przeciągnąć znacznik, użytkownik musi go długo nacisnąć. Gdy użytkownik wyjdzie z ekranu, znacznik pozostanie w tym miejscu. Po przeciągnięciu znacznika początkowo wywoływany jest element onMarkerDragStart(Marker). Podczas znacznika przesuwany jest znacznik onMarkerDrag(Marker). Na końcu przeciągania wywołuje się właściwość onMarkerDragEnd(Marker). W każdej chwili możesz sprawdzić położenie znacznika, dzwoniąc pod numer Marker.getPosition().