How to zoom between two Google map markers in flutter
To zoom between two Lat Lng bounds in google map, you can do as below:
First of all import below library in pubspec.yaml otherwise with the older version, you might not be able to see "getVisibleRegion()" method with google map controller.
google_maps_flutter: ^0.5.12
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Completer<GoogleMapController> _controller = Completer();
GoogleMapController mapController;
LatLng _lastMapPosition = _center;
static const LatLng _center = const LatLng(45.521563, -122.677433);
final Set<Marker> _markers = {};
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
_controller.complete(controller);
LatLng latLng_1 = LatLng(40.416775, -3.70379);
LatLng latLng_2 = LatLng(41.385064, 2.173403);
LatLngBounds bound = LatLngBounds(southwest: latLng_1, northeast: latLng_2);
setState(() {
_markers.clear();
addMarker(latLng_1, "Madrid", "5 Star Rating");
addMarker(latLng_2, "Barcelona", "7 Star Rating");
});
CameraUpdate u2 = CameraUpdate.newLatLngBounds(bound, 50);
this.mapController.animateCamera(u2).then((void v){
check(u2,this.mapController);
});
}
void addMarker(LatLng mLatLng, String mTitle, String mDescription){
_markers.add(Marker(
// This marker id can be anything that uniquely identifies each marker.
markerId: MarkerId((mTitle + "_" + _markers.length.toString()).toString()),
position: mLatLng,
infoWindow: InfoWindow(
title: mTitle,
snippet: mDescription,
),
icon: BitmapDescriptor.defaultMarker,
));
}
void check(CameraUpdate u, GoogleMapController c) async {
c.animateCamera(u);
mapController.animateCamera(u);
LatLngBounds l1=await c.getVisibleRegion();
LatLngBounds l2=await c.getVisibleRegion();
print(l1.toString());
print(l2.toString());
if(l1.southwest.latitude==-90 ||l2.southwest.latitude==-90)
check(u, c);
}
void _onCameraMove(CameraPosition position) {
_lastMapPosition = position.target;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Maps Sample App'),
backgroundColor: Colors.green[700],
),
body: GoogleMap(
markers: _markers,
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
onCameraMove: _onCameraMove,
),
),
);
}
}
The proposed solution above is good, but LatLngBounds has one important limitation:
LatLngBounds({@required this.southwest, @required this.northeast})
: assert(southwest != null),
assert(northeast != null),
assert(southwest.latitude <= northeast.latitude); // <--
This means that the first coordinate must be lower and to the left of the second coordinate.
I had to modify the method for different coordinates.
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
_controller.complete(controller);
//offerLatLng and currentLatLng are custom
final LatLng offerLatLng = LatLng(
double.parse(widget.coordinates.first.latLongList.first.latitude),
double.parse(widget.coordinates.first.latLongList.first.longitude));
LatLngBounds bound;
if (offerLatLng.latitude > currentLatLng.latitude &&
offerLatLng.longitude > currentLatLng.longitude) {
bound = LatLngBounds(southwest: currentLatLng, northeast: offerLatLng);
} else if (offerLatLng.longitude > currentLatLng.longitude) {
bound = LatLngBounds(
southwest: LatLng(offerLatLng.latitude, currentLatLng.longitude),
northeast: LatLng(currentLatLng.latitude, offerLatLng.longitude));
} else if (offerLatLng.latitude > currentLatLng.latitude) {
bound = LatLngBounds(
southwest: LatLng(currentLatLng.latitude, offerLatLng.longitude),
northeast: LatLng(offerLatLng.latitude, currentLatLng.longitude));
} else {
bound = LatLngBounds(southwest: offerLatLng, northeast: currentLatLng);
}
CameraUpdate u2 = CameraUpdate.newLatLngBounds(bound, 50);
this.mapController.animateCamera(u2).then((void v){
check(u2,this.mapController);
});
}