Is there a way to change Google Maps Android API v2 marker's icon during runtime without removing/re-adding the marker I want to change its icon? Can I apply transformations to it (like rotation)?
Thanks.
Only tested for Android
To change the icon of the marker at runtime I had changed the icon variable from final to non-final by removing the "final" key in Line 186:
final BitmapDescriptor icon;
BitmapDescriptor icon;
And change the Marker Constructor from "const" to "non-const" in Line 136:
const Marker({
Marker({
To make changes in a package you have to follow this instructions.
With the google_maps_flutter repo you will get a error like "Could not find pubspec.yaml". Thats because the google_maps_flutter package is placed in a subdirectory of the repository.
To get the right dependencies you have to add the specific path of the package in your pubspec.yaml:
dependencies:
# google_maps_flutter: ^2.1.1
google_maps_flutter:
git:
url: https://github.com/[username]/plugins.git
path: packages/google_maps_flutter/google_maps_flutter/
Then you able to change the icon by directly set it on the marker. I do it by using the "OnTap" Method.
Marker marker = Marker(
icon: firstIcon,
markerId: MarkerId(id),
position: position,
infoWindow: InfoWindow(
title: name,
snippet: address,
),
onTap: () {
setState(() {
_markers[name]?.icon = secondIcon;
});
}
);
The whole Marker class:
@immutable
class Marker implements MapsObject {
/// Creates a set of marker configuration options.
///
/// Default marker options.
///
/// Specifies a marker that
/// * is fully opaque; [alpha] is 1.0
/// * uses icon bottom center to indicate map position; [anchor] is (0.5, 1.0)
/// * has default tap handling; [consumeTapEvents] is false
/// * is stationary; [draggable] is false
/// * is drawn against the screen, not the map; [flat] is false
/// * has a default icon; [icon] is `BitmapDescriptor.defaultMarker`
/// * anchors the info window at top center; [infoWindowAnchor] is (0.5, 0.0)
/// * has no info window text; [infoWindowText] is `InfoWindowText.noText`
/// * is positioned at 0, 0; [position] is `LatLng(0.0, 0.0)`
/// * has an axis-aligned icon; [rotation] is 0.0
/// * is visible; [visible] is true
/// * is placed at the base of the drawing order; [zIndex] is 0.0
/// * reports [onTap] events
/// * reports [onDragEnd] events
Marker({
required this.markerId,
this.alpha = 1.0,
this.anchor = const Offset(0.5, 1.0),
this.consumeTapEvents = false,
this.draggable = false,
this.flat = false,
this.icon = BitmapDescriptor.defaultMarker,
this.infoWindow = InfoWindow.noText,
this.position = const LatLng(0.0, 0.0),
this.rotation = 0.0,
this.visible = true,
this.zIndex = 0.0,
this.onTap,
this.onDrag,
this.onDragStart,
this.onDragEnd,
}) : assert(alpha == null || (0.0 <= alpha && alpha <= 1.0));
/// Uniquely identifies a [Marker].
final MarkerId markerId;
@override
MarkerId get mapsId => markerId;
/// The opacity of the marker, between 0.0 and 1.0 inclusive.
///
/// 0.0 means fully transparent, 1.0 means fully opaque.
final double alpha;
/// The icon image point that will be placed at the [position] of the marker.
///
/// The image point is specified in normalized coordinates: An anchor of
/// (0.0, 0.0) means the top left corner of the image. An anchor
/// of (1.0, 1.0) means the bottom right corner of the image.
final Offset anchor;
/// True if the marker icon consumes tap events. If not, the map will perform
/// default tap handling by centering the map on the marker and displaying its
/// info window.
final bool consumeTapEvents;
/// True if the marker is draggable by user touch events.
final bool draggable;
/// True if the marker is rendered flatly against the surface of the Earth, so
/// that it will rotate and tilt along with map camera movements.
final bool flat;
/// A description of the bitmap used to draw the marker icon.
BitmapDescriptor icon;
/// A Google Maps InfoWindow.
///
/// The window is displayed when the marker is tapped.
final InfoWindow infoWindow;
/// Geographical location of the marker.
final LatLng position;
/// Rotation of the marker image in degrees clockwise from the [anchor] point.
final double rotation;
/// True if the marker is visible.
final bool visible;
/// The z-index of the marker, used to determine relative drawing order of
/// map overlays.
///
/// Overlays are drawn in order of z-index, so that lower values means drawn
/// earlier, and thus appearing to be closer to the surface of the Earth.
final double zIndex;
/// Callbacks to receive tap events for markers placed on this map.
final VoidCallback? onTap;
/// Signature reporting the new [LatLng] at the start of a drag event.
final ValueChanged<LatLng>? onDragStart;
/// Signature reporting the new [LatLng] at the end of a drag event.
final ValueChanged<LatLng>? onDragEnd;
/// Signature reporting the new [LatLng] during the drag event.
final ValueChanged<LatLng>? onDrag;
/// Creates a new [Marker] object whose values are the same as this instance,
/// unless overwritten by the specified parameters.
Marker copyWith({
double? alphaParam,
Offset? anchorParam,
bool? consumeTapEventsParam,
bool? draggableParam,
bool? flatParam,
BitmapDescriptor? iconParam,
InfoWindow? infoWindowParam,
LatLng? positionParam,
double? rotationParam,
bool? visibleParam,
double? zIndexParam,
VoidCallback? onTapParam,
ValueChanged<LatLng>? onDragStartParam,
ValueChanged<LatLng>? onDragParam,
ValueChanged<LatLng>? onDragEndParam,
}) {
return Marker(
markerId: markerId,
alpha: alphaParam ?? alpha,
anchor: anchorParam ?? anchor,
consumeTapEvents: consumeTapEventsParam ?? consumeTapEvents,
draggable: draggableParam ?? draggable,
flat: flatParam ?? flat,
icon: iconParam ?? icon,
infoWindow: infoWindowParam ?? infoWindow,
position: positionParam ?? position,
rotation: rotationParam ?? rotation,
visible: visibleParam ?? visible,
zIndex: zIndexParam ?? zIndex,
onTap: onTapParam ?? onTap,
onDragStart: onDragStartParam ?? onDragStart,
onDrag: onDragParam ?? onDrag,
onDragEnd: onDragEndParam ?? onDragEnd,
);
}
/// Creates a new [Marker] object whose values are the same as this instance.
Marker clone() => copyWith();
/// Converts this object to something serializable in JSON.
Object toJson() {
final Map<String, Object> json = <String, Object>{};
void addIfPresent(String fieldName, Object? value) {
if (value != null) {
json[fieldName] = value;
}
}
addIfPresent('markerId', markerId.value);
addIfPresent('alpha', alpha);
addIfPresent('anchor', _offsetToJson(anchor));
addIfPresent('consumeTapEvents', consumeTapEvents);
addIfPresent('draggable', draggable);
addIfPresent('flat', flat);
addIfPresent('icon', icon.toJson());
addIfPresent('infoWindow', infoWindow._toJson());
addIfPresent('position', position.toJson());
addIfPresent('rotation', rotation);
addIfPresent('visible', visible);
addIfPresent('zIndex', zIndex);
return json;
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other.runtimeType != runtimeType) return false;
final Marker typedOther = other as Marker;
return markerId == typedOther.markerId &&
alpha == typedOther.alpha &&
anchor == typedOther.anchor &&
consumeTapEvents == typedOther.consumeTapEvents &&
draggable == typedOther.draggable &&
flat == typedOther.flat &&
icon == typedOther.icon &&
infoWindow == typedOther.infoWindow &&
position == typedOther.position &&
rotation == typedOther.rotation &&
visible == typedOther.visible &&
zIndex == typedOther.zIndex;
}
@override
int get hashCode => markerId.hashCode;
@override
String toString() {
return 'Marker{markerId: $markerId, alpha: $alpha, anchor: $anchor, '
'consumeTapEvents: $consumeTapEvents, draggable: $draggable, flat: $flat, '
'icon: $icon, infoWindow: $infoWindow, position: $position, rotation: $rotation, '
'visible: $visible, zIndex: $zIndex, onTap: $onTap, onDragStart: $onDragStart, '
'onDrag: $onDrag, onDragEnd: $onDragEnd}';
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With