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
- MapWithMarker: prosta mapa ze znacznikiem. Zobacz samouczek na temat dodawania mapy za pomocą znacznika marker-kt.
- MarkerDemoActivity: używanie znaczników na mapie, w tym opcji i detektorów.
Java
- MapWithMarker: prosta mapa ze znacznikiem. Zapoznaj się z samouczkiem dotyczącym dodawania mapy za pomocą znacznika.
- MarkerDemoActivity: używanie znaczników na mapie, w tym opcji i detektorów.
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ść obiektuMarker
. - 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ść tofalse
. - Widoczne
- Ustaw na
false
, by znacznik był niewidoczny. Domyślna wartość totrue
. - 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
- Zdarzenia przeciągania znacznika
- Zdarzenia kliknięcia okna informacyjnego
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()
.