Mapy w pakiecie Maps SDK na Androida można przechylać i obracać za pomocą prostych gestów, dzięki czemu użytkownicy mogą dostosować mapę do orientacji, która im odpowiada. Na każdym poziomie powiększenia możesz przesuwać mapę lub zmieniać jej perspektywę z bardzo małym opóźnieniem dzięki mniejszemu rozmiarowi kafelków mapy wektorowej.
Przykładowe fragmenty kodu
Repozytorium ApiDemos w GitHubie zawiera przykład, który pokazuje funkcje aparatu:
- CameraDemoActivity – Kotlin: zmiana pozycji aparatu
- CameraDemoActivity – Java: zmiana pozycji aparatu
Wprowadzenie
Podobnie jak Mapy Google w internecie, pakiet Maps SDK na Androida przedstawia powierzchnię Ziemi (sferę) na ekranie urządzenia (płaszczyźnie) za pomocą odwzorowania Merkatora. W kierunku wschód-zachód mapa powtarza się w nieskończoność, ponieważ świat płynnie się zawija. W kierunku północ-południe mapa jest ograniczona do około 85 stopni na północ i 85 stopni na południe.
Uwaga: odwzorowanie Merkatora ma skończoną szerokość w kierunku południkowym, ale nieskończoną wysokość w kierunku równoleżnikowym. Obrazy mapy podstawowej „odcinamy” za pomocą odwzorowania Merkatora w przybliżeniu na poziomie +/- 85 stopni, aby uzyskać kwadratowy kształt mapy, co ułatwia logikę wyboru fragmentów mapy.
Pakiet Maps SDK na Androida umożliwia zmianę punktu widzenia użytkownika na mapę przez modyfikację aparatu mapy.
Zmiany w aparacie nie spowodują żadnych zmian w znacznikach, nakładkach ani innych dodanych grafikach, ale możesz je zmienić, aby lepiej pasowały do nowego widoku.
Ponieważ możesz nasłuchiwać gestów użytkownika na mapie, możesz zmieniać mapę w odpowiedzi na jego prośby. Na przykład metoda wywołania zwrotnego
OnMapClickListener.onMapClick() reaguje na
pojedyncze kliknięcie mapy. Ponieważ metoda otrzymuje szerokość i długość geograficzną miejsca kliknięcia, możesz odpowiedzieć, przesuwając lub powiększając widok do tego punktu.
Podobne metody są dostępne w przypadku reagowania na kliknięcia dymka znacznika lub na przeciągnięcie znacznika.
Możesz też nasłuchiwać ruchów aparatu, aby aplikacja otrzymywała powiadomienia, gdy aparat zaczyna się poruszać, porusza się lub przestaje się poruszać. Więcej informacji znajdziesz w przewodniku po zdarzeniach zmiany aparatu.
Pozycja aparatu
Widok mapy jest modelowany jako aparat skierowany w dół na płaską powierzchnię. Położenie aparatu (a tym samym renderowanie mapy) jest określone przez te właściwości: cel (szerokość i długość geograficzna), kierunek, nachylenie, i powiększenie.
Cel (lokalizacja)
Cel aparatu to lokalizacja środka mapy, określona jako współrzędne szerokości i długości geograficznej.
Szerokość geograficzna może się zawierać w przedziale od -85 do 85 stopni włącznie. Wartości powyżej lub poniżej tego zakresu zostaną ograniczone do najbliższej wartości w tym zakresie. Na przykład podanie szerokości geograficznej 100 spowoduje ustawienie wartości 85. Długość geograficzna mieści się w zakresie od -180 do 180 stopni włącznie. Wartości powyżej lub poniżej tego zakresu zostaną zawinięte tak, aby mieściły się w zakresie (-180, 180). Na przykład wartości 480, 840 i 1200 zostaną zawinięte do 120 stopni.Kierunek (orientacja)
Kierunek aparatu określa kierunek kompasu, mierzony w stopniach od północy geograficznej, odpowiadający górnej krawędzi mapy. Jeśli narysujesz pionową linię od środka mapy do jej górnej krawędzi, kierunek będzie odpowiadać kierunkowi aparatu (mierzony w stopniach) względem północy geograficznej.
Kierunek 0 oznacza, że górna część mapy jest skierowana na północ geograficzną. Wartość kierunku 90 oznacza, że górna część mapy jest skierowana na wschód (90 stopni na kompasie). Wartość 180 oznacza, że górna część mapy jest skierowana na południe.
Interfejs API Map Google umożliwia zmianę kierunku mapy. Na przykład kierowca często obraca mapę drogową, aby dopasować ją do kierunku jazdy, a turyści korzystający z mapy i kompasu zwykle orientują mapę tak, aby pionowa linia była skierowana na północ.
Nachylenie (kąt patrzenia)
Nachylenie określa położenie aparatu na łuku bezpośrednio nad środkiem mapy, mierzone w stopniach od zenitu (kierunku skierowanego bezpośrednio pod aparat). Wartość 0 odpowiada aparatowi skierowanemu prosto w dół. Wartości większe niż 0 odpowiadają aparatowi, który jest nachylony w kierunku horyzontu o określoną liczbę stopni. Gdy zmienisz kąt patrzenia, mapa będzie wyświetlana w perspektywie, a odległe elementy będą mniejsze, a pobliskie – większe. Ilustrują to poniższe rysunki.
Na obrazach poniżej kąt patrzenia wynosi 0 stopni. Pierwszy obraz przedstawia schemat: pozycja 1 to położenie aparatu, a pozycja 2 to bieżące położenie mapy. Poniżej znajduje się wynikowa mapa.
|
|
Na obrazach poniżej kąt patrzenia wynosi 45 stopni. Zwróć uwagę, że aparat przesuwa się w połowie łuku między położeniem bezpośrednio nad głową (0 stopni) a ziemią (90 stopni) do pozycji 3. Aparat nadal jest skierowany na środek mapy, ale widoczny jest teraz obszar reprezentowany przez linię w pozycji 4.
|
|
Mapa na tym zrzucie ekranu jest nadal wyśrodkowana w tym samym punkcie co na oryginalnej mapie, ale u góry mapy pojawiło się więcej elementów. Gdy zwiększysz kąt powyżej 45 stopni, elementy między aparatem a położeniem mapy będą proporcjonalnie większe, a elementy poza położeniem mapy będą proporcjonalnie mniejsze, co da efekt trójwymiarowy.
Zoom
Poziom powiększenia aparatu określa skalę mapy. Przy większych poziomach powiększenia na ekranie widać więcej szczegółów, a przy mniejszych – większą część świata. Przy poziomie powiększenia 0 skala mapy jest taka, że cały świat ma szerokość około 256 dp (pikseli niezależnych od gęstości).
Zwiększenie poziomu powiększenia o 1 powoduje podwojenie szerokości świata na ekranie. Dlatego przy poziomie powiększenia N szerokość świata wynosi około 256 * 2N dp. Na przykład przy poziomie powiększenia 2 cały świat ma szerokość około 1024 dp.
Poziom powiększenia nie musi być liczbą całkowitą. Zakres poziomów powiększenia dozwolonych na mapie zależy od wielu czynników, w tym od celu, typu mapy i rozmiaru ekranu. Każda liczba spoza tego zakresu zostanie przekonwertowana na najbliższą prawidłową wartość, która może być minimalnym lub maksymalnym poziomem powiększenia. Poniższa lista przedstawia przybliżony poziom szczegółowości, który można zobaczyć na każdym poziomie powiększenia:
- 1: Świat
- 5: Ląd/kontynent
- 10: Miasto
- 15: Ulice
- 20: Budynki
|
|
|
Przesuwanie aparatu
Interfejs API Map Google umożliwia zmianę części świata widocznej na mapie. Osiąga się to przez zmianę położenia aparatu (a nie przez przesuwanie mapy).
Gdy zmienisz aparat, możesz animować wynikowy ruch aparatu. Animacja interpoluje między bieżącymi a nowymi atrybutami aparatu. Możesz też kontrolować czas trwania animacji.
Aby zmienić położenie aparatu, musisz określić, gdzie chcesz go
przesunąć, używając CameraUpdate. Interfejs API Map Google
umożliwia tworzenie wielu różnych typów CameraUpdate za pomocą
CameraUpdateFactory. Dostępne są te ustawienia:
Zmiana poziomu powiększenia i ustawianie minimalnego/maksymalnego powiększenia
CameraUpdateFactory.zoomIn() i
CameraUpdateFactory.zoomOut()
dają CameraUpdate, który zmienia poziom powiększenia o 1,0, zachowując
wszystkie inne właściwości bez zmian.
CameraUpdateFactory.zoomTo(float)
daje CameraUpdate, który zmienia poziom powiększenia na podaną wartość,
zachowując wszystkie inne właściwości bez zmian.
CameraUpdateFactory.zoomBy(float)
i
CameraUpdateFactory.zoomBy(float, Point)
dają CameraUpdate, który zwiększa (lub zmniejsza, jeśli wartość jest
ujemna) poziom powiększenia o podaną wartość. Ten ostatni ustala dany punkt na ekranie tak, aby pozostał w tej samej lokalizacji (szerokość i długość geograficzna), dlatego może zmienić położenie aparatu, aby to osiągnąć.
Może się okazać, że warto ustawić preferowany minimalny lub maksymalny poziom powiększenia. Jest to przydatne np. do kontrolowania wrażeń użytkownika, jeśli aplikacja pokazuje określony obszar wokół interesującego miejsca lub jeśli używasz niestandardowej nakładki kafelków z ograniczonym zestawem poziomów powiększenia.
Kotlin
map.setMinZoomPreference(6.0f) map.setMaxZoomPreference(14.0f)
Java
map.setMinZoomPreference(6.0f); map.setMaxZoomPreference(14.0f);
Pamiętaj, że istnieją względy techniczne, które mogą uniemożliwić interfejsowi API zbyt duże lub zbyt małe powiększenie. Na przykład mapa satelitarna lub terenowa może mieć mniejszy maksymalny poziom powiększenia niż kafelki mapy podstawowej.
Zmiana pozycji aparatu
Istnieją 2 wygodne metody do typowych zmian pozycji.
CameraUpdateFactory.newLatLng(LatLng)
daje CameraUpdate, który zmienia szerokość i długość geograficzną aparatu,
zachowując wszystkie inne właściwości.
CameraUpdateFactory.newLatLngZoom(LatLng, float)
daje CameraUpdate, który zmienia szerokość, długość geograficzną i powiększenie aparatu, zachowując wszystkie inne właściwości.
Aby w pełni elastycznie zmieniać położenie aparatu, użyj
CameraUpdateFactory.newCameraPosition(CameraPosition)
który daje CameraUpdate który przesuwa aparat do
podanej pozycji. A CameraPosition można uzyskać bezpośrednio za pomocą
new CameraPosition() lub za pomocą CameraPosition.Builder za pomocą
new CameraPosition.Builder().
Przesuwanie (przewijanie)
CameraUpdateFactory.scrollBy(float, float) daje CameraUpdate który
zmienia szerokość i długość geograficzną aparatu tak, aby mapa przesuwała się o
określoną liczbę pikseli. Dodatnia wartość x powoduje przesunięcie aparatu w prawo, tak aby mapa wydawała się przesunięta w lewo. Dodatnia wartość y powoduje przesunięcie aparatu w dół, tak aby mapa wydawała się przesunięta w górę. Odwrotnie, ujemne wartości x powodują przesunięcie aparatu w lewo, tak aby mapa wydawała się przesunięta w prawo, a ujemne wartości y powodują przesunięcie aparatu w górę. Przewijanie jest względne w stosunku do bieżącej orientacji aparatu. Jeśli np. kierunek aparatu wynosi 90 stopni, wschód jest „w górę”.
Ustawianie granic
Ustawianie granic mapy
Czasami warto przesunąć aparat tak, aby cały interesujący obszar był widoczny przy największym możliwym poziomie powiększenia. Jeśli np. wyświetlasz wszystkie stacje benzynowe w promieniu 8 km od bieżącego położenia użytkownika, możesz przesunąć aparat tak, aby wszystkie były widoczne na ekranie. Aby to zrobić, najpierw oblicz
LatLngBounds, które mają być widoczne na ekranie. Następnie możesz użyć CameraUpdateFactory.newLatLngBounds(LatLngBounds bounds, int
padding), aby uzyskać CameraUpdate, który zmienia położenie aparatu tak, aby dany LatLngBounds mieścił się w całości na mapie, z uwzględnieniem określonego dopełnienia (w pikselach). Zwrócony CameraUpdate zapewnia, że odstęp (w pikselach) między danymi granicami a krawędzią mapy będzie co najmniej równy określonemu dopełnieniu. Pamiętaj, że nachylenie i kierunek mapy będą wynosić 0.
Kotlin
val australiaBounds = LatLngBounds( LatLng((-44.0), 113.0), // SW bounds LatLng((-10.0), 154.0) // NE bounds ) map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0))
Java
LatLngBounds australiaBounds = new LatLngBounds( new LatLng(-44, 113), // SW bounds new LatLng(-10, 154) // NE bounds ); map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0));
Wyśrodkowywanie mapy w obszarze
W niektórych przypadkach możesz chcieć wyśrodkować aparat w granicach zamiast uwzględniać skrajne granice. Na przykład aby wyśrodkować aparat na kraju przy zachowaniu stałego powiększenia. W takim przypadku możesz użyć podobnej metody,
tworząc LatLngBounds i używając
CameraUpdateFactory.newLatLngZoom(LatLng latLng, float zoom) z
LatLngBounds.Metoda getCenter(). Metoda getCenter() zwróci środek geograficzny LatLngBounds.
Kotlin
val australiaBounds = LatLngBounds( LatLng((-44.0), 113.0), // SW bounds LatLng((-10.0), 154.0) // NE bounds ) map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.center, 10f))
Java
LatLngBounds australiaBounds = new LatLngBounds( new LatLng(-44, 113), // SW bounds new LatLng(-10, 154) // NE bounds ); map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.getCenter(), 10));
Przeciążenie metody newLatLngBounds(boundary, width, height,
padding)
umożliwia określenie szerokości i wysokości prostokąta w pikselach, z założeniem, że odpowiadają one wymiarom mapy. Prostokąt jest umieszczony tak, aby jego środek był taki sam jak środek widoku mapy (czyli jeśli określone wymiary są takie same jak wymiary widoku mapy, prostokąt pokrywa się z widokiem mapy). Zwrócony CameraUpdate przesunie aparat tak, aby określony LatLngBounds był wyśrodkowany na ekranie w danym prostokącie przy największym możliwym poziomie powiększenia, z uwzględnieniem wymaganego dopełnienia.
Uwaga: prostszą metodę
newLatLngBounds(boundary, padding)
używaj tylko do generowania CameraUpdate, jeśli ma ona służyć do przesuwania
aparatu po ułożeniu mapy. Podczas układu interfejs API oblicza granice wyświetlania mapy, które są potrzebne do prawidłowego rzutowania ramki ograniczającej. W porównaniu z tym możesz używać
CameraUpdate zwróconego przez bardziej złożoną metodę
newLatLngBounds(boundary, width, height, padding)
w dowolnym momencie, nawet przed ułożeniem mapy, ponieważ interfejs API
oblicza granice wyświetlania na podstawie przekazanych argumentów.
Ograniczanie przesuwania użytkownika do danego obszaru
W opisanych powyżej scenariuszach ustawiasz granice mapy, ale użytkownik może przewijać lub przesuwać widok poza te granice. Zamiast tego możesz ograniczyć granice środka szerokości i długości geograficznej punktu centralnego mapy (celu aparatu) tak, aby użytkownicy mogli przewijać i przesuwać widok tylko w tych granicach. Na przykład aplikacja handlowa dla centrum handlowego lub lotniska może chcieć ograniczyć mapę do określonych granic, umożliwiając użytkownikom przewijanie i przesuwanie widoku w tych granicach.
Kotlin
// Create a LatLngBounds that includes the city of Adelaide in Australia. val adelaideBounds = LatLngBounds( LatLng(-35.0, 138.58), // SW bounds LatLng(-34.9, 138.61) // NE bounds ) // Constrain the camera target to the Adelaide bounds. map.setLatLngBoundsForCameraTarget(adelaideBounds)
Java
// Create a LatLngBounds that includes the city of Adelaide in Australia. LatLngBounds adelaideBounds = new LatLngBounds( new LatLng(-35.0, 138.58), // SW bounds new LatLng(-34.9, 138.61) // NE bounds ); // Constrain the camera target to the Adelaide bounds. map.setLatLngBoundsForCameraTarget(adelaideBounds);
Poniższy diagram ilustruje scenariusz, w którym cel aparatu jest ograniczony do obszaru nieco większego niż widoczny obszar. Użytkownik może przewijać i przesuwać widok, o ile cel aparatu pozostaje w ograniczonym obszarze. Krzyżyk reprezentuje cel aparatu:
Mapa zawsze wypełnia widoczny obszar, nawet jeśli powoduje to wyświetlanie obszarów znajdujących się poza zdefiniowanymi granicami. Jeśli np. umieścisz cel aparatu w rogu ograniczonego obszaru, obszar poza rogiem będzie widoczny w widocznym obszarze, ale użytkownicy nie będą mogli przewijać dalej w tym obszarze. Poniższy diagram ilustruje ten scenariusz. Krzyżyk reprezentuje cel aparatu:
Na poniższym diagramie cel aparatu ma bardzo ograniczone granice, co daje użytkownikowi bardzo małe możliwości przewijania lub przesuwania mapy. Krzyżyk reprezentuje cel aparatu:
Aktualizowanie widoku z aparatu
Aby zastosować CameraUpdate do mapy, możesz natychmiast przesunąć
aparat lub animować go płynnie. Aby natychmiast przesunąć aparat
za pomocą danego CameraUpdate, możesz wywołać
GoogleMap.moveCamera(CameraUpdate).
Możesz poprawić wrażenia użytkownika, zwłaszcza w przypadku krótkich ruchów, animując zmianę. Aby to zrobić, zamiast wywoływać
GoogleMap.moveCamera
, wywołaj
GoogleMap.animateCamera.
Mapa będzie się płynnie przesuwać do nowych atrybutów. Najbardziej szczegółowa forma tej metody,
GoogleMap.animateCamera(cameraUpdate, duration, callback),
ma 3 argumenty:
cameraUpdate- The
CameraUpdateopisujący, gdzie przesunąć aparat. callback- Obiekt, który implementuje
GoogleMap.CancellableCallback. Ten uogólniony interfejs do obsługi zadań definiuje 2 metody: `onCancel()` i `onFinished()`. W przypadku animacji metody są wywoływane w tych okolicznościach:onFinish()- Wywoływana, jeśli animacja zostanie ukończona bez przerwy.
onCancel()-
Wywoływana, jeśli animacja zostanie przerwana przez wywołanie
stopAnimation()lub rozpoczęcie nowego ruchu aparatu.Może się to też zdarzyć, jeśli wywołasz
GoogleMap.stopAnimation().
duration- Pożądany czas trwania animacji w milisekundach jako
int.
Poniższe fragmenty kodu ilustrują niektóre typowe sposoby przesuwania aparatu.
Kotlin
val sydney = LatLng(-33.88, 151.21) val mountainView = LatLng(37.4, -122.1) // Move the camera instantly to Sydney with a zoom of 15. map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15f)) // Zoom in, animating the camera. map.animateCamera(CameraUpdateFactory.zoomIn()) // Zoom out to zoom level 10, animating with a duration of 2 seconds. map.animateCamera(CameraUpdateFactory.zoomTo(10f), 2000, null) // Construct a CameraPosition focusing on Mountain View and animate the camera to that position. val cameraPosition = CameraPosition.Builder() .target(mountainView) // Sets the center of the map to Mountain View .zoom(17f) // Sets the zoom .bearing(90f) // Sets the orientation of the camera to east .tilt(30f) // Sets the tilt of the camera to 30 degrees .build() // Creates a CameraPosition from the builder map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
Java
LatLng sydney = new LatLng(-33.88, 151.21); LatLng mountainView = new LatLng(37.4, -122.1); // Move the camera instantly to Sydney with a zoom of 15. map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15)); // Zoom in, animating the camera. map.animateCamera(CameraUpdateFactory.zoomIn()); // Zoom out to zoom level 10, animating with a duration of 2 seconds. map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null); // Construct a CameraPosition focusing on Mountain View and animate the camera to that position. CameraPosition cameraPosition = new CameraPosition.Builder() .target(mountainView) // Sets the center of the map to Mountain View .zoom(17) // Sets the zoom .bearing(90) // Sets the orientation of the camera to east .tilt(30) // Sets the tilt of the camera to 30 degrees .build(); // Creates a CameraPosition from the builder map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));