Znaczniki identyfikują miejsca na mapie. Domyślny znacznik korzysta ze standardowej ikony, która jest typowa dla wyglądu Map Google. Za pomocą interfejsu API można zmienić kolor ikony, obraz lub punkt zakotwiczenia. Znaczniki to obiekty typu Marker
, które dodaje się do mapy za pomocą metody GoogleMap.addMarker(markerOptions)
.
Markery są interaktywne. Domyślnie otrzymują zdarzenia click
i są często 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. Kliknij i przytrzymaj, aby aktywować możliwość przesuwania znacznika.
Gdy użytkownik kliknie marker, domyślnie w prawym dolnym rogu mapy pojawi się pasek narzędzi, który umożliwi mu szybki dostęp do aplikacji mobilnej Mapy Google. Możesz wyłączyć ten pasek narzędzi. Więcej informacji znajdziesz w przewodniku po elementach sterujących.
Dodaj znacznik
Poniższy 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 „Marker in Sydney” (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 markerze
Często pojawia się potrzeba wyświetlania dodatkowych informacji o miejscu lub lokalizacji, gdy użytkownik kliknie znacznik na mapie. Zapoznaj się z przewodnikiem po oknach informacyjnych.
Powiązywanie danych ze znacznikiem
Możesz przechowywać dowolny obiekt danych z markerem za pomocą funkcji Marker.setTag()
, a pobierać go za pomocą funkcji Marker.getTag()
. Poniższy przykład pokazuje, jak za pomocą tagów zliczać kliknięcia 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 warto przechowywać i pobierać dane za pomocą znaczników:
- Aplikacja może obsługiwać różne typy znaczników, które chcesz traktować inaczej, gdy użytkownik je kliknie. Aby to zrobić, możesz zapisać
String
ze znacznikiem wskazującym typ. - Możesz korzystać z systemu, który ma unikalne identyfikatory rekordów, a znaczniki reprezentują konkretne rekordy w tym systemie.
- Dane znacznika mogą wskazywać priorytet, który należy uwzględnić przy określaniu indeksu z znacznika.
Umożliwianie przeciągania markera
Po dodaniu znacznika do mapy możesz zmienić jego położenie, 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.
Markery nie są domyślnie możliwe do przeciągania. Musisz wyraźnie ustawić, że znacznik ma być przesuwalny, używając w tym celu parametru MarkerOptions.draggable(boolean)
przed dodaniem go do mapy lub parametru 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 przesuwalny znacznik 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, jak za pomocą znaczników wizualizować lokalizacje na mapie.
Znaczniki mogą definiować niestandardowy obraz, który będzie wyświetlany zamiast ikony domyślnej. Zdefiniowanie ikony wymaga ustawienia kilku właściwości, które wpływają na wizualne zachowanie znacznika.
Znaczniki można dostosowywać za pomocą tych właściwości:
- Stanowisko (wymagane)
- Wartość
LatLng
określająca położenie znacznika na mapie. Jest to jedyna wymagana właściwość obiektuMarker
. - Kotwica
- Punkt na obrazie, który zostanie umieszczony w pozycji LatLng znacznika. Domyślnie jest on ustawiany na środku dolnej krawędzi 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 zamiast domyślnego obrazu znacznika.
- Element przeciągalny
- Ustaw wartość
true
, jeśli chcesz zezwolić użytkownikowi na przesuwanie znacznika. Domyślna wartość tofalse
. - Widoczne
- Ustaw wartość
false
, aby znacznik był niewidoczny. Domyślna wartość totrue
. - Orientacja pozioma lub pionowa
- Domyślnie markery są rysowane w orientacji billboardu, co oznacza, że są one zorientowane względem ekranu urządzenia, a nie powierzchni mapy. Obracanie, przechylanie ani powiększanie mapy nie zmienia orientacji znacznika. Możesz ustawić orientację znacznika tak, aby był płaski względem Ziemi. Płaskie znaczniki obracają się wraz z mapą i zmieniają perspektywę, gdy mapa jest przechylona. Podobnie jak w przypadku znaczników billboardowych, płaskie znaczniki zachowują swój rozmiar po powiększeniu lub pomniejszeniu mapy.
- Obrót
- Orientacja znacznika określona w stopniach zgodnie z ruchem wskazówek zegara. Domyślna pozycja zmienia się, jeśli znacznik jest płaski. Domyślna pozycja płaskiego znacznika jest ustawiona na północ. Gdy marker nie jest płaski, domyślna pozycja jest skierowana do góry, a rotacja sprawia, że marker jest zawsze skierowany w stronę kamery.
Poniższy 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 domyślnego obrazu znacznika można dostosować, 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ń to wartość z zakresu od 0 do 360, która reprezentuje punkty na kole barw.
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ść markera możesz kontrolować za pomocą metody MarkerOptions.alpha(). Wartość alfa powinna być określona jako liczba zmiennoprzecinkowa 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));
Dostosowywanie obrazu znacznika
Możesz zastąpić domyślny obraz znacznika niestandardowym obrazem znacznika, często nazywanym ikoną. Ikony niestandardowe są zawsze ustawiane jako BitmapDescriptor
i definiowane za pomocą jednej z metod w klasie BitmapDescriptorFactory
.
fromAsset(String assetName)
- Tworzy niestandardowy znacznik, używając nazwy obrazu bitmapowego w katalogu zasobów.
fromBitmap(Bitmap image)
- Tworzy niestandardowy znacznik z obrazu bitmapowego.
fromFile(String fileName)
- Tworzy niestandardową ikonę, używając nazwy pliku obrazu bitmapowego znajdującego się w pamięci wewnętrznej.
fromPath(String absolutePath)
- Tworzy niestandardowy znacznik na podstawie bezwzględnej ścieżki do pliku obrazu bitmapowego.
fromResource(int resourceId)
- Tworzy niestandardowy znacznik przy użyciu identyfikatora zasobu obrazu bitmapowego.
Poniższy fragment kodu tworzy 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łaszczanie znacznika
Ikony znaczników są zwykle rysowane względem ekranu. Obracanie, pochylanie ani powiększanie mapy nie zmienia orientacji znacznika. Możesz ustawić orientację znacznika tak, aby był płaski względem Ziemi. Znaczniki zorientowane w ten sposób będą się obracać wraz z mapą i zmieniać perspektywę, gdy mapa zostanie przechylona. Płaskie znaczniki zachowują swój rozmiar, gdy mapa jest powiększana lub pomniejszana.
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
Możesz obracać marker wokół punktu zakotwiczenia za pomocą ikony Marker
.setRotation()
. Obrót jest mierzony w stopniach zgodnie z ruchem wskazówek zegara od pozycji domyślnej. Gdy znacznik jest płasko umieszczony na mapie, domyślny kierunek to północ. Gdy znacznik nie jest płaski, domyślna pozycja to skierowanie do góry, a rotacja jest taka, że znacznik jest zawsze zwrócony w stronę kamery.
Poniższy przykład obraca znacznik o 90°. Ustawienie punktu zakotwiczenia na 0.5,0.5
powoduje obracanie 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));
Kolejność nakładania markera
Właściwość z-index określa kolejność nakładania tego znacznika względem innych znaczników na mapie. Znacznik o wysokiej wartości wskaźnika z-index jest rysowany na znacznikach o niższych wartościach tego wskaźnika. Domyślna wartość indeksu z to 0
.
Ustaw indeks z w obiekcie 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));
Dostęp do indeksu z znacznika możesz uzyskać, wywołując Marker.getZIndex()
, a zmienić go, wywołując Marker.setZIndex()
.
Markery są zawsze rysowane nad warstwami kafelków i innymi nakładkami, które nie są markerami (nakładkami na ziemię, poliliniami, wielokątami i innymi kształtami), niezależnie od wartości z-indeksu innych nakładek. Markery są traktowane jako osobna grupa indeksu z w porównaniu z innymi nakładkami.
Poniżej znajdziesz informacje o wpływie indeksu z na zdarzenia kliknięcia.
Obsługa zdarzeń związanych ze znacznikami
Interfejs Maps API umożliwia nasłuchiwanie zdarzeń związanych ze znacznikami i reagowanie na nie. Aby nasłuchiwać tych zdarzeń, musisz ustawić odpowiedni detektor na obiekcie GoogleMap
, do którego należą markery. Gdy zdarzenie wystąpi na jednym ze znaczników na mapie, wywołanie zwrotne detektora zostanie wywołane z odpowiednim obiektem Marker
przekazanym jako parametr. Aby porównać ten obiekt Marker
z własnym odniesieniem do obiektu Marker
, musisz użyć equals()
, a nie ==
.
Możesz nasłuchiwać tych zdarzeń:
Zdarzenia kliknięcia markera
Możesz użyć OnMarkerClickListener
, aby nasłuchiwać zdarzeń kliknięcia znacznika. Aby ustawić tego odbiorcę na mapie, wywołaj funkcję 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 pominąć domyślne działanie). Jeśli zwróci wartość false
, oprócz Twojego niestandardowego działania wystąpi działanie domyślne. Domyślne działanie zdarzenia kliknięcia znacznika polega na wyświetleniu jego okna informacyjnego (jeśli jest dostępne) i przesunięciu kamery tak, aby znacznik był wyśrodkowany na mapie.
Wpływ indeksu Z na zdarzenia kliknięcia:
- Gdy użytkownik kliknie klaster znaczników, zdarzenie kliknięcia zostanie wywołane w przypadku znacznika o najwyższym indeksie z.
- Na 1 kliknięcie wywoływane jest co najwyżej 1 zdarzenie. Innymi słowy, kliknięcie nie jest przekazywane do znaczników ani innych nakładek o niższych wartościach indeksu z.
- Kliknięcie klastra znaczników powoduje, że kolejne kliknięcia przełączają się między znacznikami w klastrze, wybierając każdy z nich po kolei. Kolejność cyklu jest określana najpierw na podstawie indeksu z, a potem na podstawie odległości od punktu kliknięcia.
- Jeśli użytkownik kliknie poza obszarem klastra, interfejs API ponownie obliczy klaster i zresetuje stan cyklu kliknięć, aby rozpocząć go od początku.
- Markery są traktowane jako należące do osobnej grupy indeksu z w porównaniu z innymi nakładkami lub kształtami (poliliniami, wielokątami, okręgami lub nakładkami na ziemię), niezależnie od indeksu z innych nakładek. Jeśli kilka znaczników, nakładek lub kształtów jest nałożonych na siebie, zdarzenie kliknięcia jest najpierw przekazywane do klastra znaczników.
Zdarzenia przeciągania markera
Możesz użyć OnMarkerDragListener
, aby nasłuchiwać zdarzeń przeciągania znacznika. Aby ustawić tego odbiorcę na mapie, wywołaj funkcję GoogleMap.setOnMarkerDragListener
. Aby przeciągnąć marker, użytkownik musi go przytrzymać. Gdy użytkownik odsunie palec od ekranu, znacznik pozostanie w tym miejscu. Gdy znacznik zostanie przeciągnięty, najpierw wywoływana jest funkcja
onMarkerDragStart(Marker)
. Podczas przeciągania markera funkcja onMarkerDrag(Marker)
jest wywoływana nieustannie. Na końcu operacji przeciągania wywoływana jest funkcja drag
onMarkerDragEnd(Marker)
. Położenie znacznika możesz w każdej chwili sprawdzić, wywołując funkcję Marker.getPosition()
.