Here are 3 Common features you very often need to implement with Google Maps for a Flutter App.
Visible Region from Google Maps
To determine whether a specific location is visible on the screen in Google Maps Flutter, you need to calculate if that location lies within the visible region of the map camera.
Here’s a Dart function that does exactly that:
import 'package:google_maps_flutter/google_maps_flutter.dart';
/// Returns true if [location] is visible in the current [cameraPosition] and [screenBounds].
bool isLocationVisible(
LatLng location,
CameraPosition cameraPosition,
LatLngBounds visibleRegion,
) {
final lat = location.latitude;
final lng = location.longitude;
final southwest = visibleRegion.southwest;
final northeast = visibleRegion.northeast;
final isLatVisible = lat >= southwest.latitude && lat <= northeast.latitude;
final isLngVisible = southwest.longitude <= northeast.longitude
? (lng >= southwest.longitude && lng <= northeast.longitude)
// Handle longitude wrap-around at the antimeridian
: (lng >= southwest.longitude || lng <= northeast.longitude);
return isLatVisible && isLngVisible;
}
Notes:
visibleRegionis obtained asynchronously from aGoogleMapController:
final GoogleMapController controller = ...;
LatLngBounds visibleRegion = await controller.getVisibleRegion();
- This function handles longitude wrapping around ±180° (the antimeridian), which can otherwise cause incorrect results near places like Fiji or Alaska.
Example usage:
bool visible = isLocationVisible(
myTargetLocation,
currentCameraPosition,
await mapController.getVisibleRegion(),
);
I have a list of items with GPS Location. How could I reposition the Camera of Google Maps in Flutter to fit all the coordinations
To reposition the Google Maps camera in Flutter to show all your GPS locations (markers, items, etc.), you need to:
- Compute a bounding box (
LatLngBounds) around all coordinates. - Animate the camera to fit that bounds using
GoogleMapController.
✅ Step-by-step Implementation
import 'package:google_maps_flutter/google_maps_flutter.dart';
void fitAllMarkers(List<LatLng> locations, GoogleMapController controller) {
if (locations.isEmpty) return;
// Step 1: Create bounds from list
double minLat = locations.first.latitude;
double maxLat = locations.first.latitude;
double minLng = locations.first.longitude;
double maxLng = locations.first.longitude;
for (var loc in locations) {
if (loc.latitude < minLat) minLat = loc.latitude;
if (loc.latitude > maxLat) maxLat = loc.latitude;
if (loc.longitude < minLng) minLng = loc.longitude;
if (loc.longitude > maxLng) maxLng = loc.longitude;
}
final bounds = LatLngBounds(
southwest: LatLng(minLat, minLng),
northeast: LatLng(maxLat, maxLng),
);
// Step 2: Animate camera to fit bounds
controller.animateCamera(
CameraUpdate.newLatLngBounds(bounds, 50), // 50 is padding in pixels
);
}
📌 Usage Example
// Assuming you already have the map controller
final controller = await _mapController.future;
fitAllMarkers(myLocationList, controller);
Make sure:
- Your
GoogleMapwidget is fully rendered (e.g. insideWidgetsBinding.instance.addPostFrameCallback(...)) before callingfitAllMarkers. - There are at least two points. If all markers are at the same location, you may need to set a default zoom level instead.
🛠 Optional Improvements
- Handle one-location case:
if (locations.length == 1) { controller.animateCamera( CameraUpdate.newLatLngZoom(locations.first, 15), ); return; }
How to place a Widget above the map on the top Center (width 90px), and distance from the top 30 px
You can place a widget above a GoogleMap in Flutter using a Stack. To position it at the top center, with a width of 90 pixels and 30 pixels from the top, you can use Align + Padding, or Positioned.
✅ Recommended approach using Align and Padding:
Stack(
children: [
GoogleMap(
initialCameraPosition: _initialCameraPosition,
// other map parameters
),
Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.only(top: 30),
child: Container(
width: 90,
height: 40, // optional
color: Colors.white, // just to make it visible
child: Center(child: Text('My Widget')),
),
),
),
],
);
🔄 Alternate with Positioned:
Stack(
children: [
GoogleMap(
initialCameraPosition: _initialCameraPosition,
),
Positioned(
top: 30,
left: (MediaQuery.of(context).size.width / 2) - 45, // 90 / 2
child: Container(
width: 90,
height: 40,
color: Colors.white,
child: Center(child: Text('My Widget')),
),
),
],
);
📝 The
Alignapproach is usually preferred for responsiveness and cleaner layout code, whilePositionedgives you more control if needed.
