google_maps_marker_widgets 1.1.1
google_maps_marker_widgets: ^1.1.1 copied to clipboard
A Flutter package for using widgets as markers in Google Maps.
Google Maps Marker Widgets #
A Flutter package for using widgets as markers in Google Maps.
Features #
-
Use any widget as a [Marker] on a [GoogleMap].
-
Update marker locations with smooth animations (no teleportation).
-
A customizable [LocationPuck] widget that allows for manual control over location updates and appearance.
Screenshots #
animated marker widgets | custom location puck |
---|---|
![]() |
![]() |
Getting started #
-
Install and setup google_maps_flutter if you haven't already done so.
-
If you plan on tracking the users location be sure to add the appropriate permissions.
iOS
Update your Info.plist to include permissions to access the user's location.
For foreground only access use
<key>NSLocationWhenInUseUsageDescription</key>
<string>Allow this app to access your location when in use?</string>
For apps using monitoring location data in the background use
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app works best when you allow it to track your location at all times.</string>
Android
For Android open app/src/main/AndroidManifest.xml and add one of following under the manifest tag.<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Add geolocator
and flutter_compass
(optional) #
flutter pub add geolocator
flutter pub add flutter_compass
Usage #
There are three main components to [google_maps_marker_widgets].
1. [MarkerWidget] - a widget which supplies the visual content for a [Marker] in [GoogleMap]. #
final treeMarkerId = MarkerId('treeMarker');
final treeMarkerWidget = MarkerWidget(
markerId: treeMarkerId,
child: Icon(Icons.park, color: Colors.green, size: 45),
);
2. [MarkerWidgetsController] - which manages [MarkerWidget]s and their associated [Marker]s on a [GoogleMap]. #
You use a markerWidgetsController to add, remove, and update markers.
To create a controller and add a marker
final markerWidgetsController = MarkerWidgetsController();
final treeMarker = Marker(
markerId: treeMarkerId,
anchor: Offset(0.5, 0.5),
position: LatLng(37, -108));
markerWidgetsController.addMarkerWidget(
markerWidget: treeMarkerWidget,
marker: treeMarker
);
Note the [Marker.anchor] was set to Offset(0.5, 0.5)
. This ensures the marker is centered over its position. The default anchor from [GoogleMap] is Offset(0.5, 1.0)
.
To update the position of a marker
final treeMarker = markerWidgetsController.markerForId(treeMarkerId)!;
final newPosition = LatLng(33, -105);
final updatedMarker = treeMarker.copyWith(positionParam: newPosition);
markerWidgetsController.updateMarker(marker: updatedMarker);
When updating a marker, the position is animated by default. You can pass [animated] false to disable this behavior.
3. [MarkerWidgets] - A wrapper widget for [GoogleMap]. #
[MarkerWidgets] is the main entry point for using google_maps_marker_widgets
.
Pass a [MarkerWidgetsController] to [MarkerWidgets] and in the [MarkerWidgets.builder] method create your [GoogleMap] passing in the set of supplied markers.
...
@override
Widget build(BuildContext context) {
return Scaffold(
body: MarkerWidgets(
markerWidgetsController: _markerWidgetsController,
builder: (context, markers) => GoogleMap(
initialCameraPosition:
CameraPosition(target: LatLng(41.8, -99.65), zoom: 4),
markers: markers,
),
),
);
}
Full example #
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:google_maps_marker_widgets/google_maps_marker_widgets.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Google Maps Marker Widgets Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightGreen),
useMaterial3: true,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final MarkerWidgetsController _markerWidgetsController =
MarkerWidgetsController();
@override
void initState() {
_addSampleWidgetMarkers();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: MarkerWidgets(
markerWidgetsController: _markerWidgetsController,
builder: (context, markers) => GoogleMap(
initialCameraPosition:
CameraPosition(target: LatLng(41.8, -99.65), zoom: 4),
markers: markers,
myLocationButtonEnabled: false,
),
),
floatingActionButton: FloatingActionButton(
onPressed: _moveMarkers,
child: Icon(Icons.play_arrow_rounded),
),
);
}
void _addSampleWidgetMarkers() {
//add a few sample widgets to demonstrate animation
//Note the anchor / Offset is set to 0.5, 0.5.
//This centers your widget on the position you provide.
//Make a MarkerId
final treeMarkerId = MarkerId('treeMarker');
//Add a MarkerWidget
_markerWidgetsController.addMarkerWidget(
markerWidget: MarkerWidget(
markerId: treeMarkerId,
child: Icon(Icons.park, color: Colors.green, size: 45),
),
marker: Marker(
markerId: treeMarkerId,
anchor: Offset(0.5, 0.5),
position: LatLng(37, -108)));
final smileyMarkerId = MarkerId('smileyMarker');
_markerWidgetsController.addMarkerWidget(
markerWidget: MarkerWidget(
markerId: smileyMarkerId,
child: Text(
'😀',
style: TextStyle(fontSize: 40),
),
),
marker: Marker(
markerId: smileyMarkerId,
position: LatLng(37, -101),
anchor: Offset(0.5, 0.5)));
final flightMarkerId = MarkerId('flightMarker');
_markerWidgetsController.addMarkerWidget(
markerWidget: MarkerWidget(
markerId: flightMarkerId,
child: CircleAvatar(
backgroundColor: Colors.blue,
child: Icon(
Icons.flight,
color: Colors.white,
),
)),
marker: Marker(
markerId: flightMarkerId,
anchor: Offset(0.5, 0.5),
position: LatLng(37, -93.65),
),
);
}
//Moves markers to new random locations
void _moveMarkers() {
final markers = _markerWidgetsController.markers.value;
for (var marker in markers) {
final newLat =
41.8 + Random().nextDouble() * 10 * (Random().nextBool() ? -1 : 1);
final newLng =
-99 + Random().nextDouble() * 10 * (Random().nextBool() ? -1 : 1);
final newMarker = marker.copyWith(positionParam: LatLng(newLat, newLng));
_markerWidgetsController.updateMarker(newMarker);
}
}
}
Issues and Contributing #
If you find any bugs or want to help add features file an issue on GitHub.
Author #
Developed by Jonathan Badger PharmD, MS