简体   繁体   中英

Setting max zoom level in google maps android api v2

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?

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.

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));
}

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);

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;
}

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);
    }
}

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

Im not sure if this will work but can you try this

map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);

Hope it helps

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

@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;
}

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");
        }
    }
});

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 .

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));
}

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);

        }
    });
map.setMinZoomPreference(floatValue);

Zoom Levels are the followings:

 1f: World 5f: Landmass/continent 10f: City 15f: Streets 20f: Buildings
val setMin = 10f
val setMax = 20f

googleMap.setMaxZoomPreference(setMax)
googleMap.setMinZoomPreference(setMin)

您可以通过调用getMaxZoomLevel()来获得最大缩放级别,然后设置该值:

mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(fromPosition, getMaxZoomLevel()));

The map has a property called maxZoom. Simply set this to your value when you create your map

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM