可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm currently working on developing apps by using Google maps android API v2.
My code is as follows.
Suppose map has several markers and zoom up to show all markers in display.
LatLngBuilder.Builder builder = LatLngBounds.builder();
for(Marker m : markers){
builder.include(m.getPosition());
}
LatLngBounds bounds = builder.build();
map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10);
This code is working fine but I want to stop animating when the zoom level reached to 17.0f;
It seems map API does not have such method to control zoom level.
Does anybody know any idea to solve this problem?
回答1:
I have not found any direct solution in the Google Maps API. A potential solution to this problem consists in listening against the OnCameraChange event: Whenever this event triggers and the zoom level is above the maximum zoom level, it is possible to call animateCamera(). The resulting code would be the following:
@Override
public void onCameraChange(CameraPosition position) {
float maxZoom = 17.0f;
if (position.zoom > maxZoom)
map_.animateCamera(CameraUpdateFactory.zoomTo(maxZoom));
}
回答2:
A recent update to the Google Maps API introduces the functions you require:
GoogleMap.setMaxZoomPreference()
GoogleMap.setMinZoomPreference()
It still does not prevent the animation from playing, though.
回答3:
Here is the corresponding Java code for Arvis' solution which worked well for me:
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;
}
回答4:
From Android doc:
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);
回答5:
Same as Arvis solution but using Location
's [distanceBetween()
](http://developer.android.com/reference/android/location/Location.html#distanceBetween(double, double, double, double, float[])) method to calculate distance between to points:
@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);
}
}
回答6:
Before animate Camera you can check if SW and NE points of bounds are not too close and if necessary adjust bounds:
...
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. My example is in c# for Xamarin but you can easly adjust it for java
回答7:
This is from the API reference for the include(position)
you're using:
"Includes this point for building of the bounds. The bounds will be extended in a minimum way to include this point.
More precisely, it will consider extending the bounds both in the eastward and westward directions (one of which may wrap around the world) and choose the smaller of the two. In the case that both directions result in a LatLngBounds of the same size, this will extend it in the eastward direction."
The map will zoom out until it can show all of the markers you're adding in your for loop.
If you want to only zoom out to 17 and still show markers, animate to zoom level 17 first, then get the bounds for it, and then add your markers.
@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
回答8:
@kasimir's approach sets a minimum number of degrees in either the latitude or longitude, and felt a little hard to read. So I tweaked it to just set a minimum on the latitude, which I felt like was a bit more readable:
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;
}
回答9:
Im not sure if this will work but can you try this
map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);
Hope it helps
回答10:
What I ended up doing is creating my own buttons and disabling the default ones so I would have full control.
Something like this in the layout to place the buttons:
<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>
Then this in the code to disable the default buttons and setup our new ones:
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");
}
}
});
回答11:
With com.google.android.gms:play-services-maps:9.4.0
you can easily set min/max zoom. With GoogleMap.setMinZoomPreference()
and GoogleMap.setMaxZoomPreference()
you can set a prefered minimum and/or maximum zoom level. More see here.
回答12:
We can not restrict map zoomin feature directly, but we can try to get same feature like this.
add map.setOnCameraChangeListener
final float maxZoom = 10.0f;
@Override
public void onCameraChange(CameraPosition position) {
if (position.zoom > maxZoom)
map.animateCamera(CameraUpdateFactory.zoomTo(maxZoom));
}
回答13:
On the new Google Maps 9.8
com.google.android.gms:play-services-maps:9.8.0
This is how I did and worked
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);
}
});
回答14:
map.setMinZoomPreference(floatValue);
回答15:
You can get the max zoom level by calling it getMaxZoomLevel()
and then set that value:
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(fromPosition, getMaxZoomLevel()));
回答16:
The map has a property called maxZoom. Simply set this to your value when you create your map