Flutter LatLngBounds not showing accurate place
Asked Answered
L

4

6

I am trying to show all of my markers into the viewport using my flutter google maps. But it seems not working in my case. I have tried so far as below:

    _controller.animateCamera(CameraUpdate.newLatLngBounds(
            LatLngBounds(
              southwest: LatLng(23.785182, 90.330702),
              northeast: LatLng(24.582782, 88.821163),
            ),
            100
        ));

    LatLngBounds boundsFromLatLngList(List<LatLng> list) {
    assert(list.isNotEmpty);
    double x0, x1, y0, y1;
    for (LatLng latLng in list) {
      if (x0 == null) {
        x0 = x1 = latLng.latitude;
        y0 = y1 = latLng.longitude;
      } else {
        if (latLng.latitude > x1) x1 = latLng.latitude;
        if (latLng.latitude < x0) x0 = latLng.latitude;
        if (latLng.longitude > y1) y1 = latLng.longitude;
        if (latLng.longitude < y0) y0 = latLng.longitude;
      }
    }
    return LatLngBounds(northeast: LatLng(x1, y1), southwest: LatLng(x0, y0));
  }

As i have seen, it just always show the map of North Atlantic Ocean Is there any solution regarding this issue or it is just under development in Flutter ?. thanks in advance

Learn answered 11/5, 2020 at 5:50 Comment(3)
I am having the same problem. On iOS it works fine, but on android CameraUpdate.newLatLngBounds always zoom out to max and show middle of the ocean. No matter what you pass as coordinates.Cuprite
@ZigmārsDzērve I'm facing the exact same issue on android, iOS seems to work fine. Did you manage to find a workaround for this?Omnipotent
@ChinmayDabke Yes, but it was a dirty hack for Android only. I calculated the center position between my points and then calculated zoom level and did normal a normal _controller.animateCamera(u2); when zoom level and the center position is known. It's an unnecessary work, but it works around the problem google maps currently have.Cuprite
O
8

I'm facing the exact same issue on Android (works fine on iOS) when I animate the map with CameraUpdate.newLatLngBounds. It repositions to North Pacific Ocean immediately after setting the bounds, not sure what's causing this but here's a workaround -

Instead of setting the map position using LatLngBounds, you can calculate the centre of the bounds you want to set

// the bounds you want to set
LatLngBounds bounds = LatLngBounds(
  southwest: LatLng(23.785182, 90.330702),
  northeast: LatLng(24.582782, 88.821163),
);
// calculating centre of the bounds
LatLng centerBounds = LatLng(
  (bounds.northeast.latitude + bounds.southwest.latitude)/2,
  (bounds.northeast.longitude + bounds.southwest.longitude)/2
);

// setting map position to centre to start with
controller.moveCamera(CameraUpdate.newCameraPosition(CameraPosition(
  target: centerBounds,
  zoom: 17,
)));
zoomToFit(controller, bounds, centerBounds);

Once you set the map position to the centre of the bounds (and zoomed in), you then need to keep zooming out till the visible map region covers the bounds you want to set. You can get the visible map region with controller.getVisibleRegion(). Here's the implementation -

Future<void> zoomToFit(GoogleMapController controller, LatLngBounds bounds, LatLng centerBounds) async {
  bool keepZoomingOut = true;

  while(keepZoomingOut) {
    final LatLngBounds screenBounds = await controller.getVisibleRegion();
    if(fits(bounds, screenBounds)){
      keepZoomingOut = false;
      final double zoomLevel = await controller.getZoomLevel() - 0.5;
      controller.moveCamera(CameraUpdate.newCameraPosition(CameraPosition(
        target: centerBounds,
        zoom: zoomLevel,
      )));
      break;
    }
    else {
      // Zooming out by 0.1 zoom level per iteration
      final double zoomLevel = await controller.getZoomLevel() - 0.1;
      controller.moveCamera(CameraUpdate.newCameraPosition(CameraPosition(
        target: centerBounds,
        zoom: zoomLevel,
      )));
    }
  }
}

bool fits(LatLngBounds fitBounds, LatLngBounds screenBounds) {
  final bool northEastLatitudeCheck = screenBounds.northeast.latitude >= fitBounds.northeast.latitude;
  final bool northEastLongitudeCheck = screenBounds.northeast.longitude >= fitBounds.northeast.longitude;

  final bool southWestLatitudeCheck = screenBounds.southwest.latitude <= fitBounds.southwest.latitude;
  final bool southWestLongitudeCheck = screenBounds.southwest.longitude <= fitBounds.southwest.longitude;

  return northEastLatitudeCheck && northEastLongitudeCheck && southWestLatitudeCheck && southWestLongitudeCheck;
}
Omnipotent answered 15/6, 2020 at 21:41 Comment(0)
P
2

i found this way that work for me perfectly .

Future<void> updateCameraLocation(
  LatLng source,
  LatLng destination,
  GoogleMapController mapController,
) async {
  if (mapController == null) return;

  LatLngBounds bounds;

  if (source.latitude > destination.latitude &&
      source.longitude > destination.longitude) {
    bounds = LatLngBounds(southwest: destination, northeast: source);
  } else if (source.longitude > destination.longitude) {
    bounds = LatLngBounds(
        southwest: LatLng(source.latitude, destination.longitude),
        northeast: LatLng(destination.latitude, source.longitude));
  } else if (source.latitude > destination.latitude) {
    bounds = LatLngBounds(
        southwest: LatLng(destination.latitude, source.longitude),
        northeast: LatLng(source.latitude, destination.longitude));
  } else {
    bounds = LatLngBounds(southwest: source, northeast: destination);
  }

  CameraUpdate cameraUpdate = CameraUpdate.newLatLngBounds(bounds, 70);

  return checkCameraLocation(cameraUpdate, mapController);
}

Future<void> checkCameraLocation(
    CameraUpdate cameraUpdate, GoogleMapController mapController) async {
  mapController.animateCamera(cameraUpdate);
  LatLngBounds l1 = await mapController.getVisibleRegion();
  LatLngBounds l2 = await mapController.getVisibleRegion();

  if (l1.southwest.latitude == -90 || l2.southwest.latitude == -90) {
    return checkCameraLocation(cameraUpdate, mapController);
  }
}

And use by this line :

await updateCameraLocation(source, destination, controller);
Pianism answered 30/11, 2021 at 23:0 Comment(1)
How to set bound among 3 cordinates?Deepseated
P
1

Had the same issue the problem for me:

I didn't really gave the southwest and northeast coordinates but: NorthWest and SouthEast. iOS handled this normally but android zoomed on the Atlantic.

After fixing that like:

final highestLat = points.map((e) => e.latitude).reduce(max);
final highestLong = points.map((e) => e.longitude).reduce(max);
final lowestLat = points.map((e) => e.latitude).reduce(min);
final lowestLong = points.map((e) => e.longitude).reduce(min);

final lowestLatLowestLong = LatLng(lowestLat, lowestLong);
final highestLatHighestLong = LatLng(highestLat, highestLong);
final getRouteBoundsCameraUpdate = CameraUpdate.newLatLngBounds(LatLngBounds(southwest: lowestLatLowestLong, northeast: highestLatHighestLong), 25.0);
Putrescine answered 3/4, 2021 at 14:25 Comment(0)
A
0

I also had this issue, try swapping the southwest value with northeast value

Acetophenetidin answered 23/8, 2020 at 12:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.