Android map v2 zoom, aby pokazać wszystkie znaczniki
Mam 10 markerów w GoogleMap
. Chcę powiększyć jak najwięcej i zachować wszystkie znaczniki w widoku? We wcześniejszej wersji można to osiągnąć z zoomToSpan()
, ale w v2 nie mam pojęcia, jak to zrobić. Co więcej, Znam promień okręgu, który musi być widoczny.
13 answers
Powinieneś użyć klasy CameraUpdate
do wykonywania (prawdopodobnie) wszystkich programowych ruchów map.
Aby to zrobić, najpierw Oblicz granice wszystkich markerów tak:
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (Marker marker : markers) {
builder.include(marker.getPosition());
}
LatLngBounds bounds = builder.build();
Następnie uzyskaj obiekt opisu ruchu za pomocą fabryki: CameraUpdateFactory
:
int padding = 0; // offset from edges of the map in pixels
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
Wreszcie przenieś mapę:
googleMap.moveCamera(cu);
Lub jeśli chcesz animację:
googleMap.animateCamera(cu);
To wszystko:)
Wyjaśnienie 1
Prawie wszystkie metody ruchu wymagają, aby obiekt Map
miał przeszedł proces układ. Możesz poczekać na to, używając addOnGlobalLayoutListener
construct. Szczegóły można znaleźć w komentarzach do tej odpowiedzi i pozostałych odpowiedzi. Możesz również znaleźć kompletny kod do ustawiania zakresu mapy za pomocą addOnGlobalLayoutListener
tutaj.
Wyjaśnienie 2
Jeden komentarz zauważa, że użycie tej metody tylko dla jednego znacznika powoduje ustawienie powiększenia mapy na "dziwaczny" poziom powiększenia (który moim zdaniem jest maksymalnym poziomem powiększenia dostępnym dla danej lokalizacji). Myślę, że to jest oczekiwane ponieważ:
- instancja
LatLngBounds bounds
będzie miała właściwośćnortheast
równąsouthwest
, co oznacza, że część powierzchni Ziemi objęta tąbounds
jest dokładnie równa zeru. (Jest to logiczne, ponieważ pojedynczy znacznik nie ma obszaru.) - przechodząc
bounds
doCameraUpdateFactory.newLatLngBounds
zasadniczo żądasz obliczenia takiego poziomu powiększenia, żebounds
(z zerowym obszarem) pokryje cały widok mapy. - można faktycznie wykonać te obliczenia na kartce papieru. Teoretyczny zoom poziom, który jest odpowiedzią to + ∞ (dodatnia nieskończoność). W praktyce obiekt
Map
nie obsługuje tej wartości, więc jest zaciśnięty do bardziej rozsądnego maksymalnego poziomu dozwolonego dla danej lokalizacji.
Inaczej mówiąc: skąd Map
obiekt może wiedzieć, jaki poziom powiększenia powinien wybrać dla pojedynczej lokalizacji? Może optymalna wartość powinna wynosić 20 (jeśli reprezentuje konkretny adres). A może 11 (jeśli reprezentuje miasto). A może 6 (jeśli reprezentuje państwo). API to nie to mądrze i decyzja należy do ciebie.
Więc, należy po prostu sprawdzić, czy markers
ma tylko jedną lokalizację, a jeśli Tak, użyj jednego z:
-
CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition())
- przejdź do pozycji znacznika, pozostaw aktualny poziom powiększenia nienaruszony. -
CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F)
- przejdź do pozycji znacznika, ustaw poziom powiększenia na dowolnie wybraną wartość 12.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:30
Google Map V2
Poniższe rozwiązanie działa dla Androida Marshmallow 6 (API 23, API 24, API 25, API 26, API 27, API 28). Działa również w Xamarin.
LatLngBounds.Builder builder = new LatLngBounds.Builder();
//the include method will calculate the min and max bound.
builder.include(marker1.getPosition());
builder.include(marker2.getPosition());
builder.include(marker3.getPosition());
builder.include(marker4.getPosition());
LatLngBounds bounds = builder.build();
int width = getResources().getDisplayMetrics().widthPixels;
int height = getResources().getDisplayMetrics().heightPixels;
int padding = (int) (width * 0.10); // offset from edges of the map 10% of screen
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, width, height, padding);
mMap.animateCamera(cu);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-20 11:37:01
Więc
Musiałem użyć addOnGlobalLayoutListener, aby uzyskać odpowiednią próbkę
Na przykład, Twoja mapa Google jest wewnątrz RelativeLayout:
RelativeLayout mapLayout = (RelativeLayout)findViewById(R.id.map_layout);
mapLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//and write code, which you can see in answer above
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-04 11:43:49
Nie mogłem użyć onGlobalLayoutlistener, więc tutaj jest inne rozwiązanie, aby zapobiec
"Map size can't be 0. Most likely, layout has not yet occured for the map view. Either wait until layout has occurred or use newLatLngBounds(LatLngBounds, int, int, int) which allows you to specify the map's dimensions."
błąd:
mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
@Override
public void onMapLoaded() {
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 15));
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-15 08:31:48
Dla mnie działa dobrze.
Z tego kodu wyświetlam wiele znaczników ze szczególnym powiększeniem na ekranie mapy.
// zmienne Deklarowane
private LatLngBounds bounds;
private LatLngBounds.Builder builder;
/ / metoda dodawania wielu punktów znacznika z rysowalną ikoną
private void drawMarker(LatLng point, String text) {
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(point).title(text).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon));
mMap.addMarker(markerOptions);
builder.include(markerOptions.getPosition());
}
// do dodawania wielu znaczników widocznych na mapie
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
builder = new LatLngBounds.Builder();
for (int i = 0; i < locationList.size(); i++) {
drawMarker(new LatLng(Double.parseDouble(locationList.get(i).getLatitude()), Double.parseDouble(locationList.get(i).getLongitude())), locationList.get(i).getNo());
}
bounds = builder.build();
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
mMap.animateCamera(cu);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-05 11:20:37
Uwaga - nie jest to rozwiązanie pierwotnego pytania. Jest to rozwiązanie jednego z podproblemów omówionych powyżej.
Rozwiązanie @ andr Wyjaśnienie 2 -
Jest to naprawdę problematyczne, gdy w granicach jest tylko jeden znacznik, a dzięki temu poziom powiększenia jest ustawiony na bardzo wysoki (Poziom 21 ). A Google nie zapewnia żadnego sposobu, aby ustawić maksymalny poziom powiększenia w tym momencie. Może się to zdarzyć również wtedy, gdy jest więcej niż 1 marker, ale wszyscy są blisko siebie. Wtedy pojawi się również ten sam problem.
Rozwiązanie - Załóżmy, że chcesz, aby Twoja mapa nigdy nie przekraczała poziomu powiększenia 16. Następnie po zrobieniu -
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
mMap.moveCamera(cu);
Sprawdź, czy twój poziom powiększenia przekroczył poziom 16 (lub cokolwiek chcesz) -
float currentZoom = mMap.getCameraPosition().zoom;
I jeśli ten poziom jest większy niż 16, co będzie tylko wtedy, gdy jest bardzo mniej znaczników lub wszystkie znaczniki są bardzo blisko siebie, po prostu pomniejsz mapę w tym konkretnym miejscu tylko ustawiając poziom powiększenia na 16.
mMap.moveCamera(CameraUpdateFactory.zoomTo(16));
W ten sposób nigdy nie będziesz miał problemu z "dziwacznym" poziomem powiększenia wyjaśnionego bardzo dobrze przez @andr.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:49
To by pomogło.. od google API demos
private List<Marker> markerList = new ArrayList<>();
Marker marker = mGoogleMap.addMarker(new MarkerOptions().position(geoLatLng)
.title(title));
markerList.add(marker);
// Pan to see all markers in view.
// Cannot zoom to bounds until the map has a size.
final View mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView();
if (mapView!=null) {
if (mapView.getViewTreeObserver().isAlive()) {
mapView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@SuppressWarnings("deprecation") // We use the new method when supported
@SuppressLint("NewApi") // We check which build version we are using.
@Override
public void onGlobalLayout() {
//Calculate the markers to get their position
LatLngBounds.Builder b = new LatLngBounds.Builder();
for (Marker m : markerList) {
b.include(m.getPosition());
}
// also include current location to include in the view
b.include(new LatLng(mLocation.getLatitude(),mLocation.getLongitude()));
LatLngBounds bounds = b.build();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
}
});
}
}
Aby uzyskać jasne informacje, spójrz na ten adres url. https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-29 11:35:05
Miałem podobny problem, używając poniższego kodu rozwiązałem problem:
CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 5)
generalnie różnice w lokalizacji w moim przypadku to nie więcej niż dwa sąsiednie miasta.
Powiększ, aby dopasować wszystkie znaczniki na mapie google maps v2
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-12 12:17:38
Mam jeszcze jeden sposób, aby zrobić to samo działa idealnie. tak więc idea Za, aby pokazać wszystkie znaczniki na ekranie musimy środek lat długi i poziom powiększenia. oto funkcja, która da ci oba i potrzebuje wszystkich obiektów latlng markera jako danych wejściowych.
public Pair<LatLng, Integer> getCenterWithZoomLevel(LatLng... l) {
float max = 0;
if (l == null || l.length == 0) {
return null;
}
LatLngBounds.Builder b = new LatLngBounds.Builder();
for (int count = 0; count < l.length; count++) {
if (l[count] == null) {
continue;
}
b.include(l[count]);
}
LatLng center = b.build().getCenter();
float distance = 0;
for (int count = 0; count < l.length; count++) {
if (l[count] == null) {
continue;
}
distance = distance(center, l[count]);
if (distance > max) {
max = distance;
}
}
double scale = max / 1000;
int zoom = ((int) (16 - Math.log(scale) / Math.log(2)));
return new Pair<LatLng, Integer>(center, zoom);
}
Ta funkcja zwraca obiekt pary, którego możesz użyć jak
Para Para = getCenterWithZoomLevel (l1, l2,l3..); mGoogleMap.moveCamera (CameraUpdateFactory.newLatLngZoom (para.pierwszy, para.second));
Możesz zamiast używać paddingu, aby trzymać markery z dala od granic ekranu, możesz dostosować powiększenie o -1.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-14 09:18:03
Pokaż wszystkie znaczniki z mapą Google
W tych metodach Przechowuj wszystkie znaczniki i automatycznie powiększaj, aby wyświetlić wszystkie znaczniki na mapie google.
// Declare the Markers List.
List<MarkerOptions> markerList;
private BitmapDescriptor vnrPoint,banPoint;
public void storeAllMarkers()
{
markerList=new ArrayList<>();
markerList.removeAll(markerList);
// latitude and longitude of Virudhunagar
double latitude1=9.587209;
double longitude1=77.951431;
vnrPoint=BitmapDescriptorFactory.fromResource(R.drawable.location_icon_1);
LatLng vnr = new LatLng(latitude1, longitude1);
MarkerOptions vnrMarker = new MarkerOptions();
vnrMarker.position(vnr);
vnrMarker.icon(vnrPoint);
markerList.add(vnrMarker);
// latitude and longitude of Bengaluru
double latitude2=12.972442;
double longitude2=77.580643;
banPoint=BitmapDescriptorFactory.fromResource(R.drawable.location_icon_2);
LatLng ban = new LatLng(latitude2, longitude2);
MarkerOptions bengalureMarker = new MarkerOptions();
bengalureMarker.position(ban);
bengalureMarker.icon(banPoint);
markerList.add(bengalureMarker);
// You can add any numbers of MarkerOptions like this.
showAllMarkers();
}
public void showAllMarkers()
{
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (MarkerOptions m : markerList) {
builder.include(m.getPosition());
}
LatLngBounds bounds = builder.build();
int width = getResources().getDisplayMetrics().widthPixels;
int height = getResources().getDisplayMetrics().heightPixels;
int padding = (int) (width * 0.30);
// Zoom and animate the google map to show all markers
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, width, height, padding);
googleMap.animateCamera(cu);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-16 12:15:06
Użyj metody "getCenterCoordinate", aby uzyskać współrzędną Środkową i użyj w kamerze.
private void setUpMap() {
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setScrollGesturesEnabled(true);
mMap.getUiSettings().setTiltGesturesEnabled(true);
mMap.getUiSettings().setRotateGesturesEnabled(true);
clientMarker = mMap.addMarker(new MarkerOptions()
.position(new LatLng(Double.valueOf(-12.1024174), Double.valueOf(-77.0262274)))
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_taxi))
);
clientMarker = mMap.addMarker(new MarkerOptions()
.position(new LatLng(Double.valueOf(-12.1024637), Double.valueOf(-77.0242617)))
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_location))
);
camPos = new CameraPosition.Builder()
.target(getCenterCoordinate())
.zoom(17)
.build();
camUpd3 = CameraUpdateFactory.newCameraPosition(camPos);
mMap.animateCamera(camUpd3);
}
public LatLng getCenterCoordinate(){
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(new LatLng(Double.valueOf(-12.1024174), Double.valueOf(-77.0262274)));
builder.include(new LatLng(Double.valueOf(-12.1024637), Double.valueOf(-77.0242617)));
LatLngBounds bounds = builder.build();
return bounds.getCenter();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-23 19:08:05
Pracowałem nad tym samym problemem przy pokazywaniu wielu znaczników w Kotlinie przy użyciu fragmentu
Najpierw zadeklaruj listę znaczników
private lateinit var markers: MutableList<Marker>
Zainicjalizuj to w metodzie oncreate frament
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
//initialize markers list
markers = mutableListOf()
return inflater.inflate(R.layout.fragment_driver_map, container, false)
}
Na OnMapReadyCallback Dodaj znaczniki do listy znaczników
private val callback = OnMapReadyCallback { googleMap ->
map = googleMap
markers.add(
map.addMarker(
MarkerOptions().position(riderLatLng)
.title("Driver")
.snippet("Driver")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED))))
markers.add(
map.addMarker(
MarkerOptions().position(driverLatLng)
.title("Driver")
.snippet("Driver")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))))
Wciąż na wywołaniu zwrotnym
//create builder
val builder = LatLngBounds.builder()
//loop through the markers list
for (marker in markers) {
builder.include(marker.position)
}
//create a bound
val bounds = builder.build()
//set a 200 pixels padding from the edge of the screen
val cu = CameraUpdateFactory.newLatLngBounds(bounds,200)
//move and animate the camera
map.moveCamera(cu)
//animate camera by providing zoom and duration args, callBack set to null
map.animateCamera(CameraUpdateFactory.zoomTo(10f), 2000, null)
Merry coding guys
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-16 06:03:10
//For adding a marker in Google map
MarkerOptions mp = new MarkerOptions();
mp.position(new LatLng(Double.parseDouble(latitude), Double.parseDouble(longitude)));
mp.snippet(strAddress);
map.addMarker(mp);
try {
b = new LatLngBounds.Builder();
if (MapDetailsList.list != null && MapDetailsList.list.size() > 0) {
for (int i = 0; i < MapDetailsList.list.size(); i++) {
b.include(new LatLng(Double.parseDouble(MapDetailsList.list.get(i).getLatitude()),
Double.parseDouble(MapDetailsList.list.get(i).getLongitude())));
}
LatLngBounds bounds = b.build();
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
// Change the padding as per needed
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, width-200, height-200, 5);
// map.setCenter(bounds.getCenter());
map.animateCamera(cu);
}
} catch (Exception e) {
}
Http://i64.tinypic.com/2qjybh4.png
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-05 12:29:09