Add bounds to map to avoid swiping outside a certain region

前端 未结 9 1131
抹茶落季
抹茶落季 2021-02-01 12:45

My app shows a map and i want that users can\'t swipe over a certain region. So i\'m trying to add bounds but it makes the app to crash. Here is the working code:



        
相关标签:
9条回答
  • 2021-02-01 13:16
    Caused by: java.lang.IllegalStateException: Map size should not be 0. Most likely, layout has not yet occured for the map view.
    

    The reason Behind this error is because the Map layout has not been completed, You should implement OnMapReadyCallback in your calls, which will ensure that your code will only run after your layout is completed or Implement the below callback

    map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
        @Override
        public void onCameraChange(CameraPosition arg0) {
        map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 30));
    }
    });
    

    Duplicate Links

    moveCamera with CameraUpdateFactory.newLatLngBounds crashes

    IllegalStateException map size should not be 0

    I don't if there is a way to merge this link. I Hope i helped

    0 讨论(0)
  • 2021-02-01 13:24

    You can use MapLoadedCallBack;

    map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
      @Override
      public void onMapLoaded() {
          map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 30));
      }
    });
    

    and also you can use this event that occurs prier to above.

      map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
            @Override
            public void onCameraChange(CameraPosition arg0) {
            map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 30));
      }
    });
    
    0 讨论(0)
  • 2021-02-01 13:25

    This worked for me:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        mMapFragment.getMapAsync(this);
    }
    
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMapFragment.getView().getViewTreeObserver().addOnGlobalLayoutListener(this);
    }
    
    @Override
    public void onGlobalLayout() {
        mMapFragment.getView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
        //Only after onMapReady & onGlobalLayout newLatLngBounds will be available
        initMapPosition(); //newLatLngBounds here
    }
    
    0 讨论(0)
  • 2021-02-01 13:25

    I've created a way to combine the two callbacks: onMapReady and onGlobalLayout into one single observable which will emit only when both the events have been triggered.

    https://gist.github.com/abhaysood/e275b3d0937f297980d14b439a8e0d4a

    public final class OnMapAndLayoutReady {
    
    private OnMapAndLayoutReady() {
    }
    
    /**
     * Converts {@link OnMapReadyCallback} to an observable.
     * Note that this method calls {@link MapView#getMapAsync(OnMapReadyCallback)} so you there is no
     * need to initialize google map view manually.
     */
    private static Observable<GoogleMap> loadMapObservable(final MapView mapView) {
        return Observable.create(new Observable.OnSubscribe<GoogleMap>() {
            @Override
            public void call(final Subscriber<? super GoogleMap> subscriber) {
                OnMapReadyCallback mapReadyCallback = new OnMapReadyCallback() {
                    @Override
                    public void onMapReady(GoogleMap googleMap) {
                        subscriber.onNext(googleMap);
                    }
                };
                mapView.getMapAsync(mapReadyCallback);
            }
        });
    }
    
    /**
     * Converts {@link ViewTreeObserver.OnGlobalLayoutListener} to an observable.
     * This methods also takes care of removing the global layout listener from the view.
     */
    private static Observable<MapView> globalLayoutObservable(final MapView view) {
        return Observable.create(new Observable.OnSubscribe<MapView>() {
            @Override
            public void call(final Subscriber<? super MapView> subscriber) {
                final ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                        subscriber.onNext(view);
                    }
                };
                view.getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener);
            }
        });
    }
    
    /**
     * Takes {@link #globalLayoutObservable(MapView)} and {@link #loadMapObservable(MapView)} and zips their result.
     * This means that the subscriber will only be notified when both the observables have emitted.
     */
    public static Observable<GoogleMap> onMapAndLayoutReadyObservable(final MapView mapView) {
        return Observable.zip(globalLayoutObservable(mapView), loadMapObservable(mapView), new Func2<MapView, GoogleMap, GoogleMap>() {
            @Override
            public GoogleMap call(MapView mapView, GoogleMap googleMap) {
                return googleMap;
            }
        });
    }
    }
    
    0 讨论(0)
  • 2021-02-01 13:27

    You can keep the error from occurring by following the advice from the log:

    "...use newLatLngBounds(LatLngBounds, int, int, int) which allows you to specify the map's dimensions."

    The extra parameters are the width and height of your screen. Here's how your updated code would look:

    LatLngBounds.Builder builder = new LatLngBounds.Builder();
    builder.include(new LatLng(47.09194444, 18.52166666));
    builder.include(new LatLng(36.448311, 6.62555555));
    LatLngBounds bounds = builder.build();
    
    // begin new code:
    int width = getResources().getDisplayMetrics().widthPixels;
    int height = getResources().getDisplayMetrics().heightPixels;
    int padding = (int) (width * 0.12); // offset from edges of the map 12% of screen
    
    CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, width, height, padding);
    // end of new code
    
    map.animateCamera(cu);
    
    0 讨论(0)
  • 2021-02-01 13:28

    Caused by: java.lang.IllegalStateException: Error using newLatLngBounds(LatLngBounds, int): 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.

    From the docs https://developer.android.com/reference/com/google/android/gms/maps/CameraUpdateFactory.html#newLatLngBounds(com.google.android.gms.maps.model.LatLngBounds, int)

    Do not change the camera with this camera update until the map has undergone layout (in order for this method to correctly determine the appropriate bounding box and zoom level, the map must have a size). Otherwise an IllegalStateException will be thrown. It is NOT sufficient for the map to be available (i.e. getMap() returns a non-null object); the view containing the map must have also undergone layout such that its dimensions have been determined. If you cannot be sure that this has occured, use newLatLngBounds(LatLngBounds, int, int, int) instead and provide the dimensions of the map manually.

    Note: getMap() could return null. It is better to check for Availability of Google play services before initialize GoogleMap object.

    0 讨论(0)
提交回复
热议问题