Ho 10 marcatori nel GoogleMap
. Voglio ingrandire il più possibile e mantenere tutti i marcatori in vista? Nella versione precedente questo può essere ottenuto da zoomToSpan()
ma in v2 non ho idea di come farlo. Inoltre, conosco il raggio del cerchio che deve essere visibile.Mappa Android zoom v2 per mostrare tutti i marcatori
risposta
È necessario utilizzare la classe CameraUpdate
per eseguire (probabilmente) tutti i movimenti di mappa programmatici.
Per fare questo, prima di calcolare i limiti di tutti i marcatori in questo modo:
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (Marker marker : markers) {
builder.include(marker.getPosition());
}
LatLngBounds bounds = builder.build();
quindi ottenere un oggetto Descrizione del movimento utilizzando la fabbrica: CameraUpdateFactory
:
int padding = 0; // offset from edges of the map in pixels
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
spostare Infine la mappa :
googleMap.moveCamera(cu);
Oppure se si desidera un'animazione:
googleMap.animateCamera(cu);
Questo è tutto :)
Chiarificazione 1
Quasi tutti i metodi richiedono movimento dell'oggetto Map
aver superato il processo di layout. È possibile attendere che ciò accada utilizzando il costrutto addOnGlobalLayoutListener
. Dettagli possono essere trovati nei commenti a questa risposta e alle restanti risposte. È inoltre possibile trovare un complete code for setting map extent using addOnGlobalLayoutListener
here.
Chiarimento 2
Un commento fa notare che l'utilizzo di questo metodo per un solo risultati marcatori nella cartina set zoom ad un livello di zoom "bizzarro" (che credo di essere il massimo livello di zoom disponibili per determinato luogo). Credo che questo è previsto perché:
- L'istanza
LatLngBounds bounds
avrànortheast
struttura uguale asouthwest
, significa che la porzione della superficie della terra oggetto della presentebounds
è esattamente uguale a zero. (Questo è logico poiché un singolo marcatore non ha area.) - Passando da
bounds
aCameraUpdateFactory.newLatLngBounds
, si richiede essenzialmente un calcolo di tale livello di zoom chebounds
(con area zero) coprirà l'intera visualizzazione della mappa. - È possibile eseguire questo calcolo su un foglio di carta. Il livello di zoom teorico che è la risposta è + ∞ (infinito positivo). In pratica l'oggetto
Map
non supporta questo valore, quindi è bloccato a un livello massimo più ragionevole consentito per una determinata posizione.
Un altro modo per dirla: come può Map
oggetto sapere quale livello di zoom dovrebbe optare per un unico luogo? Forse il valore ottimale dovrebbe essere 20 (se rappresenta un indirizzo specifico). O forse 11 (se rappresenta una città). O forse 6 (se rappresenta un paese). L'API non è così intelligente e la decisione spetta a te.
Quindi, si dovrebbe semplicemente controllare se markers
ha una sola posizione e, in caso affermativo, utilizzare uno dei:
CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition())
- andare a posizione del marker, lasciare intatto il livello di zoom corrente.CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F)
- andare a posizione del marker, insieme al livello di zoom scelto arbitrariamente il valore 12.
Va notato che lo spostamento non può avvenire dalle chiamate onCreate, la vista deve essere creata. Avevo bisogno di usare addOnGlobalLayoutListener per ottenere il campione appropriato. –
@Bar Bene, questo è in parte vero. Per essere precisi: * alcuni * metodi di movimento non funzioneranno subito dopo aver creato l'oggetto mappa. La ragione di ciò è che l'oggetto della mappa non è stato * misurato * eppure non ha subito il processo di layout. Una tipica soluzione è usare 'addOnGlobalLayoutListener()' o 'post()' con un appropriato 'Runnable'. Questo è esattamente il motivo per cui non è possibile ottenere coordinate dello schermo dell'indicatore in 'onCreate' - vedere http://stackoverflow.com/q/14429877/1820695 Tuttavia * è possibile * utilizzare alcuni metodi anche prima che il layout sia successo, ad es. 'CameraUpdateFactory.newLatLngBounds()' con * 4 parametri *. – andr
Uomo, mi hai salvato la giornata ... stavo davvero provando a farlo da solo, calcola i limiti manualmente, e lo zoom mentre il marcatore è in esso ... stava lavorando molto brutto, ma con il tuo metodo semplice, funziona come un incantesimo . Grazie – Bibu
Così
I needed to use addOnGlobalLayoutListener to get the appropriate sample
ad esempio, Google Map è all'interno 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
}
});
Non potrei usare il onGlobalLayoutlistener, quindi ecco un'altra soluzione per prevenire l'errore "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."
:
mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
@Override
public void onMapLoaded() {
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 15));
}
});
Questo richiede molto più tempo di OnGlobalLayoutListener, quindi per me ha comunque mostrato il mappa prima l'area predefinita/zoom, prima di spostare la fotocamera secondo le mie esigenze – Till
Utilizzare il metodo "getCenterCoordinate" per ottenere la coordinata centrale e utilizzarla in CameraPosition.
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();
}
//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
Nota - Questa non è una soluzione alla domanda iniziale. Questa è una soluzione a uno dei sottoproblemi discussi above.
soluzione per @andr Chiarimento 2 -
sua davvero problematico quando c'è un solo marcatore nei limiti ed a causa di essa il livello di zoom è impostato su un livello molto elevato (livello 21). E Google non fornisce alcun modo per impostare il livello di zoom massimo a questo punto. Questo può accadere anche quando ci sono più di 1 segnalino, ma sono tutti abbastanza vicini l'uno all'altro. Quindi si verificherà anche lo stesso problema.
Soluzione - Supponiamo che si desideri che la mappa non superi mai il livello di zoom 16. Poi, dopo aver fatto -
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
mMap.moveCamera(cu);
Verificare che il livello di zoom ha attraversato il livello 16 (o quello che volete) -
float currentZoom = mMap.getCameraPosition().zoom;
E se questo livello è maggiore di 16, che sarà solo in caso di sono molto meno marcatori o tutti gli indicatori sono molto vicini gli uni agli altri, quindi è sufficiente diminuire la vostra mappa in quella particolare posizione solo dal seting il livello di zoom a 16.
mMap.moveCamera(CameraUpdateFactory.zoomTo(16));
in questo modo non dovrete mai la p roblema del livello di zoom "bizzarro" spiegato molto bene anche da @andr.
buona soluzione ma se metti l'oggetto "cu" dentro onMapReady(), allora c'è un comportamento scorretto in questo caso: ** posizione ricevuta -> lo zoom è grande quindi fai it 16 -> quindi l'utente esegue lo zoom in -> posizione nuovamente ricevuta e la telecamera torna al livello 16 **. Questo può essere un problema quando la posizione viene ricevuta quasi in tempo reale poiché continuerà a tornare al livello 16. –
"E Google non fornisce alcun modo per impostare il livello massimo di zoom a questo punto." - Non vero: https : //developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.html#setMaxZoomPreference (float) – user1209216
questo aiuterebbe ..da google apis demo
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));
}
});
}
}
per informazioni chiare guarda questo indirizzo. https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java
Google Map V2: MarkerOptions Zoom entro i limiti migliore soluzione di lavoro per Android Marshmallow 6 (API 23, API 24, API 25), così, lavori in Xamarin anche
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);
Working fine for me.
Da questo codice, sto visualizzando più marcatori con particolare zoom sulla schermata della mappa.
variabili // dichiarati
private LatLngBounds bounds;
private LatLngBounds.Builder builder;
// metodo per aggiungere più punti di marcatori con l'icona drawable
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());
}
// Per l'aggiunta di più marcatori visibile sulla mappa
@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);
I ha avuto un problema simile, utilizzando il seguente codice risolto il problema:
CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 5)
generalmente le differenze di località nel mio caso non sono più di due città vicine.
ho un altro modo per fare la stessa cosa funziona perfettamente. quindi l'idea alla base di mostrare tutti i marcatori sullo schermo abbiamo bisogno di un centro lat lungo e il livello di zoom. ecco la funzione che ti darà entrambi e avrà bisogno di tutti gli oggetti Latlng di un marker come input.
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);
}
Questo oggetto paio di ritorno funzione che è possibile utilizzare come
Pair pair = getCenterWithZoomLevel(l1,l2,l3..); mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(pair.first, pair.second));
è possibile invece di utilizzare imbottitura per tenere lontano i tuoi marcatori da limiti dello schermo, è possibile regolare lo zoom per -1.
La mia risposta ti fornirà una soluzione più semplice per le ultime apis Android. http://stackoverflow.com/a/38013331/1348522 –