Znaczniki

Wybierz platformę: Android iOS JavaScript

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

Przykładowe fragmenty kodu

Repozytorium API Apigee na GitHubie zawiera przykład, który ilustruje różne funkcje znaczników:

Kotlin

Java

Wstęp

Znaczniki wskazują lokalizacje na mapie. Znacznik domyślny zawiera standardową ikonę typową dla wyglądu i sposobu działania Map Google. Można zmienić kolor, obraz lub punkt zakotwiczenia ikony za pomocą interfejsu API. Znaczniki są obiektami typu Marker i są dodawane do mapy za pomocą metody GoogleMap.addMarker(markerOptions).

Znaczniki zostały zaprojektowane tak, aby były interaktywne. Otrzymują one domyślnie zdarzenia click i często są używane z detektorami zdarzeń do wyświetlania okien informacyjnych. Ustawienie właściwości draggable znacznika na true umożliwia użytkownikowi zmianę jego pozycji. Przytrzymaj, by aktywować możliwość przesunięcia znacznika.

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

Wprowadzenie do znaczników

W tym odcinku Maps Live omówiliśmy 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 zostanie utworzony w miejscu o współrzędnych -33.852,151.211 (Sydney, Australia) i po kliknięciu wyświetla ciąg „Marker in Sydney” w oknie informacyjnym.

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świetl dodatkowe informacje o znaczniku

Częstym wymaganiem jest wyświetlanie dodatkowych informacji o miejscu lub lokalizacji, gdy użytkownik kliknie znacznik na mapie. Zapoznaj się z przewodnikiem po oknach informacyjnych.

Powiąż dane ze znacznikiem

Za pomocą funkcji Marker.setTag() możesz przechowywać dowolne obiekty danych ze znacznikiem, a obiekty danych pobierać za pomocą Marker.getTag(). Poniższy przykład pokazuje, jak zliczać kliknięcia znacznika za pomocą tagów:

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 warto przechowywać i pobierać dane za pomocą znaczników:

  • Twoja aplikacja może obsługiwać różne typy znaczników i chcesz, aby były traktowane inaczej, gdy użytkownik je klika. W tym celu możesz zapisać obiekt String ze znacznikiem wskazującym typ.
  • Być może korzystasz z systemu z unikalnymi identyfikatorami rekordów, gdzie znaczniki reprezentują konkretne rekordy w tym systemie.
  • Dane znacznika mogą wskazywać priorytet, który ma być używany przy wybieraniu kolejności z-index znacznika.

Ustawianie znacznika z możliwością przeciągania

Po dodaniu znacznika do mapy możesz zmienić jego położenie, o ile jego właściwość draggable ma wartość true. Przytrzymaj znacznik, aby włączyć przeciąganie. Gdy zdejmiesz palec z ekranu, znacznik pozostanie w tym miejscu.

Domyślnie nie można przeciągać znaczników. Musisz jawnie ustawić znacznik jako możliwy do przeciągania za pomocą elementu MarkerOptions.draggable(boolean) przed dodaniem go do mapy lub Marker.setDraggable(boolean) po dodaniu go do mapy. Możesz nasłuchiwać zdarzeń przeciągania w znaczniku zgodnie z opisem w sekcji Zdarzenia przeciągania przez znaczniki.

Poniższy fragment kodu dodaje znacznik, który można przeciągać w 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 użycia znaczników do wizualizacji lokalizacji na mapie.

Znaczniki mogą wskazywać niestandardowy obraz, który będzie wyświetlany zamiast domyślnej ikony. Definiowanie ikony obejmuje ustawienie szeregu właściwości, które mają wpływ na wygląd znacznika.

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

Pozycja (wymagana)
Wartość LatLng pozycji znacznika na mapie. To jedyna wymagana właściwość obiektu Marker.
Kotwica
Punkt na obrazie, który zostanie umieszczony w pozycji położenia geograficznego znacznika. Domyślnie jest to środek dolnej części obrazu.
Alfa
Ustawia przezroczystość znacznika. Domyślna wartość to 1,0.
Tytuł
Ciąg znaków wyświetlany w oknie informacyjnym, gdy użytkownik kliknie znacznik.
Krótki opis
Dodatkowy tekst wyświetlany pod tytułem.
Ikona
Bitmapa wyświetlana w miejscu domyślnego obrazu znacznika.
Możliwość przeciągania
Ustaw na true, jeśli chcesz zezwolić użytkownikowi na przeniesienie znacznika. Domyślna wartość to false.
Widoczne
Ustaw na false, by znacznik był niewidoczny. Domyślna wartość to true.
Orientacja płaska lub billboardowa
Domyślnie znaczniki mają orientację billboardu, co oznacza, że są rysowane w kierunku ekranu urządzenia, a nie względem powierzchni mapy. Obracanie, przechylanie lub powiększanie mapy nie zmienia orientacji znacznika. Możesz ustawić płaską orientację znacznika względem ziemi. Płaskie znaczniki obracają się, gdy mapa jest obrócona, i zmieniają perspektywę, gdy jest przechylona. Tak jak w przypadku znaczników billboardów, płaskie znaczniki zachowują swój rozmiar po powiększeniu lub pomniejszeniu mapy.
Rotacja
Orientacja znacznika, podana w stopniach w prawo. Położenie domyślne zmieni się, jeśli znacznik będzie płaski. Domyślne położenie znacznika płaskiego jest wyrównane do północy. Gdy znacznik nie jest płaski, położenie domyślne jest skierowane w górę, a obrót jest tak, że znacznik jest zawsze skierowany w stronę kamery.

Poniższy fragment kodu pozwala utworzyć prosty znacznik z ikoną domyślną.

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

Można dostosować kolor domyślnego obrazu znacznika, przekazując obiekt BitmapDescriptor do metody icon(). 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). Odcień jest wartością z zakresu od 0 do 360 i 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

Przezroczystość znacznika można kontrolować za pomocą metody MarkOptions.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ą nieprzezroczystość.

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

      

Dostosuj obraz znacznika

Domyślny obraz znacznika możesz zastąpić niestandardowym obrazem znacznika, często nazywanym ikoną. Ikony niestandardowe są zawsze ustawiane jako BitmapDescriptor i definiowane za pomocą jednej z metod klasy BitmapDescriptorFactory.

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

Poniższy fragment kodu pozwala utworzyć znacznik z ikoną niestandardową.

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łaszcz znacznik

Ikony znaczników są zwykle rysowane względem ekranu. Obracanie, przechylanie lub powiększanie mapy nie zmienia orientacji znacznika. Możesz ustawić orientację znacznika tak, aby leżała płasko na ziemi. Znaczniki z taką zorientacją będą się obracać, gdy mapa jest obrócona, i zmieniać perspektywę, gdy jest przechylona. Płaskie znaczniki zachowują swój rozmiar przy powiększeniu lub pomniejszeniu mapy.

Aby zmienić orientację znacznika, ustaw właściwość flat znacznika 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

Aby obrócić znacznik wokół punktu zakotwiczenia, użyj elementu Marker.Metoda setRotation(). Obrót jest mierzony w stopniach w prawo od pozycji domyślnej. Jeśli znacznik jest na płaskiej mapie, domyślną położeniem jest północ. Gdy znacznik nie jest płaski, domyślnym położeniem jest strzałka w górę i obrót w taki sposób, że znacznik jest zawsze skierowany w stronę kamery.

Przykład poniżej obraca znacznik o 90°. Ustawienie punktu zakotwiczenia na 0.5,0.5 powoduje obrót znacznika wokół jego ś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));

      

Znacznik z-index

Kolejność nakładania elementów określa porządek, w którym dane znaczniki są ułożone względem innych znaczników na mapie. Nad znacznikami o niższych współczynnikach z-indeks zostanie narysowany znacznik o wysokim z-indeksie. Domyślna wartość z-index to 0.

Ustaw kolejność nakładania elementów w obiekcie opcji znacznika, wywołując funkcję MarkerOptions.zIndex() w sposób podany 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 wartości z-index znacznika, wywołaj funkcję Marker.getZIndex(). Aby ją zmienić, wywołaj Marker.setZIndex().

Znaczniki są zawsze rysowane nad warstwami kafelków i innymi nieznacznikami (nakładkami podłożowymi, liniami łamanymi, wielokątami i innymi kształtami) niezależnie od kolejności nakładania pozostałych nakładek. Znaczniki są w praktyce uważane za znajdujące się w osobnej grupie z-index niż inne nakładki.

Więcej informacji o wpływie kolejności nakładania elementów na zdarzenia kliknięć znajdziesz poniżej.

Obsługa zdarzeń znaczników

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

Możesz nasłuchiwać tych zdarzeń:

Zdarzenia kliknięcia znacznika

Możesz użyć OnMarkerClickListener, aby nasłuchiwać zdarzeń kliknięć znacznika. Aby ustawić ten detektor na mapie, wywołaj GoogleMap.setOnMarkerClickListener(OnMarkerClickListener). Gdy użytkownik kliknie znacznik, zostanie wywołana funkcja onMarkerClick(Marker), a znacznik zostanie przekazany jako argument. Ta metoda zwraca wartość logiczną, która wskazuje, czy zdarzenie zostało wykorzystane (tzn. czy chcesz powstrzymać działanie domyślne). Jeśli zwróci wartość false, spowoduje to dodatkowe działanie domyślne. Domyślnym zachowaniem zdarzenia kliknięcia znacznika jest wyświetlenie jego okna informacyjnego (jeśli jest dostępne) i przesunięcie kamery w taki sposób, aby znacznik był wyśrodkowany na mapie.

Wpływ ustawienia z-index na zdarzenia kliknięcia:

  • Gdy użytkownik kliknie klaster znaczników, w przypadku znacznika o najwyższym wskaźniku z-index wywoływane jest zdarzenie kliknięcia.
  • Na każde kliknięcie wyzwalane jest maksymalnie 1 zdarzenie. Oznacza to, że kliknięcie nie jest przekazywane do znaczników ani innych nakładek o niższych wartościach z-index.
  • Kliknięcie grupy znaczników powoduje cykliczne kliknięcia klastra i wybór każdego z nich po kolei. W kolejności cyklu najważniejsze są najpierw wartości z-index, a następnie bliskość punktu kliknięcia.
  • Jeśli użytkownik kliknie reklamę poza obszarem klastra, interfejs API ponownie obliczy klaster i zresetuje stan cyklu kliknięcia, tak aby zaczynał się od początku.
  • Przed ponownym rozpoczęciem cyklu zdarzenie kliknięcia przechodzi przez klastry znaczników do innych kształtów i nakładek.
  • Znaczniki uznaje się za znajdujące się w osobnej grupie z-index w porównaniu z innymi nakładkami lub kształtami (linie łamane, wielokąty, okręgi i/lub nakładki ziemne), niezależnie od kolejności nakładania pozostałych nakładek. W przypadku nałożenia na siebie wielu znaczników, nakładek lub kształtów zdarzenie kliknięcia jest najpierw cyklicznie wskazywane przez grupę znaczników, a następnie jest wywoływane dla innych klikalnych nakładek lub kształtów na podstawie ich wartości z-index.

Zdarzenia przeciągania znacznika

Za pomocą OnMarkerDragListener możesz nasłuchiwać zdarzeń przeciągania ze znacznika. Aby ustawić ten detektor na mapie, wywołaj GoogleMap.setOnMarkerDragListener. Aby przeciągnąć znacznik, użytkownik musi go przytrzymać. Gdy użytkownik odejdzie palec od ekranu, znacznik pozostanie w tym miejscu. Po przeciągnięciu znacznika nazwa onMarkerDragStart(Marker) jest początkowo wywoływana. Gdy znacznik jest przeciągnięty, funkcja onMarkerDrag(Marker) jest wywoływana stale. Na końcu przeciągania jest wywoływana funkcja onMarkerDragEnd(Marker). Położenie znacznika możesz sprawdzić w każdej chwili, wywołując funkcję Marker.getPosition().