Ich arbeite derzeit an der Entwicklung von Apps mithilfe von Google Maps Android API v2 . Mein Code lautet wie folgt . Angenommen, map hat mehrere Markierungen und eine Vergrößerung, um alle Markierungen in der Anzeige anzuzeigen.
LatLngBuilder.Builder builder = LatLngBounds.builder();
for(Marker m : markers){
builder.include(m.getPosition());
}
LatLngBounds bounds = builder.build();
map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10);
Dieser Code funktioniert einwandfrei, aber ich möchte die Animation abbrechen, wenn die Zoomstufe 17.0f erreicht hat.... Die Karten-API hat offenbar keine solche Methode, um die Zoomstufe zu steuern. Weiß jemand eine Idee, dieses Problem zu lösen?
Ich habe keine direkte Lösung in der Google Maps-API gefunden. Eine mögliche Lösung für dieses Problem besteht im Abhören des OnCameraChange-Ereignisses : Wenn dieses Ereignis ausgelöst wird und die Zoomstufe über der maximalen Zoomstufe liegt, können Sie animateCamera () aufrufen. Der resultierende Code wäre der folgende:
@Override
public void onCameraChange(CameraPosition position) {
float maxZoom = 17.0f;
if (position.zoom > maxZoom)
map_.animateCamera(CameraUpdateFactory.zoomTo(maxZoom));
}
Ein aktuelles update der Google Maps API stellt die Funktionen vor, die Sie benötigen:
GoogleMap.setMaxZoomPreference()
GoogleMap.setMinZoomPreference()
Die Wiedergabe der Animation wird jedoch immer noch nicht verhindert.
Hier ist der entsprechende Java-Code für Arvis 'Lösung, der für mich gut funktioniert hat:
private LatLngBounds adjustBoundsForMaxZoomLevel(LatLngBounds bounds) {
LatLng sw = bounds.southwest;
LatLng ne = bounds.northeast;
double deltaLat = Math.abs(sw.latitude - ne.latitude);
double deltaLon = Math.abs(sw.longitude - ne.longitude);
final double zoomN = 0.005; // minimum zoom coefficient
if (deltaLat < zoomN) {
sw = new LatLng(sw.latitude - (zoomN - deltaLat / 2), sw.longitude);
ne = new LatLng(ne.latitude + (zoomN - deltaLat / 2), ne.longitude);
bounds = new LatLngBounds(sw, ne);
}
else if (deltaLon < zoomN) {
sw = new LatLng(sw.latitude, sw.longitude - (zoomN - deltaLon / 2));
ne = new LatLng(ne.latitude, ne.longitude + (zoomN - deltaLon / 2));
bounds = new LatLngBounds(sw, ne);
}
return bounds;
}
Über Android-Dokument: https://developers.google.com/maps/documentation/Android-api/views
You may find it useful to set a prefered minimum and/or maximum zoom level. For example, this is useful to control the user's experience if your app shows a defined area around a point of interest, or if you're using a custom tile overlay with a limited set of zoom levels.
private GoogleMap mMap;
// Set a preference for minimum and maximum zoom.
mMap.setMinZoomPreference(6.0f);
mMap.setMaxZoomPreference(14.0f);
Wie Arvis-Lösung, jedoch unter Verwendung von Location
s [distanceBetween()
] ( http://developer.Android.com/reference/Android/location/Location.html#distanceBetween(double , double, double, double , float [])) Methode zur Berechnung der Entfernung zwischen Punkten:
@Override
public void zoomToMarkers(Set<Marker> markers) {
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (Marker marker : markers) {
builder.include(marker.getPosition());
}
LatLngBounds bounds = builder.build();
// Calculate distance between northeast and southwest
float[] results = new float[1];
Android.location.Location.distanceBetween(bounds.northeast.latitude, bounds.northeast.longitude,
bounds.southwest.latitude, bounds.southwest.longitude, results);
CameraUpdate cu = null;
if (results[0] < 1000) { // distance is less than 1 km -> set to zoom level 15
cu = CameraUpdateFactory.newLatLngZoom(bounds.getCenter(), 15);
} else {
int padding = 50; // offset from edges of the map in pixels
cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
}
if (cu != null) {
mMap.moveCamera(cu);
}
}
Bevor Sie die Kamera animieren, können Sie prüfen, ob SW- und NE-Grenzpunkte nicht zu eng sind, und gegebenenfalls die Grenzwerte anpassen:
...
LatLngBounds bounds = builder.Build();
var sw = bounds.Southwest;
var ne = bounds.Northeast;
var deltaLat = Math.Abs(sw.Latitude - ne.Latitude);
var deltaLon = Math.Abs(sw.Longitude - ne.Longitude);
const double zoomN = 0.005; // set whatever zoom coefficient you need!!!
if (deltaLat < zoomN) {
sw.Latitude = sw.Latitude - (zoomN - deltaLat / 2);
ne.Latitude = ne.Latitude + (zoomN - deltaLat / 2);
bounds = new LatLngBounds(sw, ne);
}
else if (deltaLon < zoomN) {
sw.Longitude = sw.Longitude - (zoomN - deltaLon / 2);
ne.Longitude = ne.Longitude + (zoomN - deltaLon / 2);
bounds = new LatLngBounds(sw, ne);
}
map.animateCamera(CameraUpdateFactory.NewLatLngBounds(bounds, 10);
ps. Mein Beispiel ist in c # für Xamarin, aber Sie können es leicht für Java anpassen
Dies ist aus der API-Referenz für die von Ihnen verwendete include(position)
:
"Enthält diesen Punkt zum Erstellen der Begrenzungen. Die Begrenzungen werden auf ein Minimum erweitert, um diesen Punkt einzuschließen. Genauer gesagt, es wird in Betracht gezogen, die Begrenzungen sowohl nach Osten als auch nach Westen zu erweitern (eine davon kann umlaufen) die Welt) und wählen Sie die kleinere der beiden. Wenn beide Richtungen zu LatLngBounds der gleichen Größe führen, wird dies nach Osten verlängert. "
Die Karte wird verkleinert, bis alle in der for-Schleife hinzugefügten Marker angezeigt werden.
Wenn Sie nur bis 17 herauszoomen und Markierungen anzeigen lassen möchten, animieren Sie zunächst die Zoomstufe 17, erhalten Sie die Grenzen und fügen Sie Ihre Markierungen hinzu.
@Override
public void onCameraChange(CameraPosition camPos) {
if (camPos.zoom < 17 && mCurrentLoc != null) {
// set zoom 17 and disable zoom gestures so map can't be zoomed out
// all the way
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(position,17));
mMap.getUiSettings().setZoomGesturesEnabled(false);
}
if (camPos.zoom >= 17) {
mMap.getUiSettings().setZoomGesturesEnabled(true);
}
LatLngBounds visibleBounds = mMap.getProjection().getVisibleRegion().latLngBounds;
//add the markers
Der Ansatz von @kasimir legt eine Mindestanzahl von Graden in Breiten- oder Längengraden fest und fühlte sich ein wenig schwer zu lesen. Also habe ich es angepasst, um nur ein Minimum an der geografischen Breite zu setzen, was meiner Meinung nach etwas lesbarer war:
private LatLngBounds adjustBoundsForMinimumLatitudeDegrees(LatLngBounds bounds, double minLatitudeDegrees) {
LatLng sw = bounds.southwest;
LatLng ne = bounds.northeast;
double visibleLatitudeDegrees = Math.abs(sw.latitude - ne.latitude);
if (visibleLatitudeDegrees < minLatitudeDegrees) {
LatLng center = bounds.getCenter();
sw = new LatLng(center.latitude - (minLatitudeDegrees / 2), sw.longitude);
ne = new LatLng(center.latitude + (minLatitudeDegrees / 2), ne.longitude);
bounds = new LatLngBounds(sw, ne);
}
return bounds;
}
Mit com.google.Android.gms:play-services-maps:9.4.0
können Sie den Min/Max-Zoom leicht einstellen. Mit GoogleMap.setMinZoomPreference()
und GoogleMap.setMaxZoomPreference()
können Sie eine bevorzugte minimale und/oder maximale Zoomstufe einstellen. Mehr dazu siehe hier .
Wir können die Karten-Zoom-Funktion nicht direkt einschränken, aber wir können versuchen, dieselbe Funktion wie diese zu erhalten.
add map.setOnCameraChangeListener
final float maxZoom = 10.0f;
@Override
public void onCameraChange(CameraPosition position) {
if (position.zoom > maxZoom)
map.animateCamera(CameraUpdateFactory.zoomTo(maxZoom));
}
map.setMinZoomPreference(floatValue);
Auf dem neuen Google Maps 9.8
com.google.Android.gms:play-services-maps:9.8.0
So habe ich gearbeitet und gearbeitet
googleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
@Override
public void onCameraMove() {
Log.d(App.TAG, "onCameraMove");
CameraPosition position = googleMap.getCameraPosition();
float maxZoom = 9.0f;
if (position.zoom > maxZoom) {
googleMap.setMinZoomPreference(maxZoom);
}
Log.d(App.TAG, "position.zoom = " + position.zoom);
}
});
Am Ende habe ich meine eigenen Schaltflächen erstellt und die Standardschaltflächen deaktiviert, damit ich volle Kontrolle habe.
So etwas im Layout, um die Schaltflächen zu platzieren:
<LinearLayout
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:orientation="vertical"
Android:layout_gravity="bottom"
Android:layout_alignParentRight="true"
Android:layout_alignParentBottom="true">
<Button
Android:id="@+id/bzoomin"
Android:layout_width="55dp"
Android:layout_height="55dp"
Android:gravity="center"
Android:textSize="28sp"
Android:text="+" />
<Button
Android:id="@+id/bzoomout"
Android:layout_width="55dp"
Android:layout_height="55dp"
Android:gravity="center"
Android:textSize="23sp"
Android:text="—" />
</LinearLayout>
Dann im Code die Standardschaltflächen deaktivieren und unsere neuen einrichten:
map.getUiSettings().setZoomControlsEnabled(false);
// setup zoom control buttons
Button zoomout = (Button) findViewById(R.id.bzoomout);
zoomout.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
if(map.getCameraPosition().zoom >= 8.0f){
// Zoom like normal
map.animateCamera(CameraUpdateFactory.zoomOut());
}else{
// Do whatever you want if user went too far
Messages.toast_short(MapsActivity.this, "Maximum zoom out level reached");
}
}
});
Button zoomin = (Button) findViewById(R.id.bzoomin);
zoomin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (map.getCameraPosition().zoom <= 14.0f) {
// Zoom like normal
map.animateCamera(CameraUpdateFactory.zoomIn());
} else {
// Do whatever you want if user went too far
Messages.toast_short(MapsActivity.this, "Maximum zoom in level reached");
}
}
});
Ich bin nicht sicher, ob dies funktioniert, aber Sie können es versuchen
map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);
Ich hoffe es hilft