I'm trying to update the coordinates of a marker (Google Maps flutter)
I'm 'creating' the marker like this.
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
Uint8List resizedMarkerImageBytesTemp = await convertUserImage(
"imgurl");
MarkerId id = MarkerId(uid);
Marker _marker = Marker(
markerId: id,
onTap: () {
print("tapped");
},
position: LatLng(lat, lng),
icon: BitmapDescriptor.fromBytes(resizedMarkerImageBytesTemp),
infoWindow: InfoWindow(title: 'myTitle'),
);
setState(() {
markers[id] = _marker;
});
What's the best / most efficient way to update the coordinates of a marker?
Thanks!
UPDATE: I tried the following.
MarkerId id = MarkerId(uid); //uid of the marker I want to update
markers[id].position.longitude = 3.12493;
But then I get the error:
error: 'longitude' can't be used as a setter because it is final.
You can create a function and pass the markerId to replace the actual marker:
updateMarker(id){
final marker = markers.values.toList().firstWhere((item) => item.markerId == id);
Marker _marker = Marker(
markerId: marker.markerId,
onTap: () {
print("tapped");
},
position: LatLng(marker.position.latitude, marker.position.longitude),
icon: marker.icon,
infoWindow: InfoWindow(title: 'my new Title'),
);
setState(() {
//the marker is identified by the markerId and not with the index of the list
markers[id] = _marker;
});
}
You can easily use this code anywhere you want to change the position:
setState((){markers[id]=markers[id].copyWith(positionParam:LatLng(yournewlat,your new long));});
You can even use it in marker on tap callback.
Related
I'm currently building an application that displays markers on a Google Map. The location of the markers is being pulled from a Firestore database. Currently, I am successfully retrieving and displaying all markers. However, I need to update the icon of each marker based on their boolean value in the database.
Here is how I am currently displaying the markers.
I create the map in the main build:
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: mapToggle
? GoogleMap(
onMapCreated: onMapCreated,
compassEnabled: false,
polylines: route,
initialCameraPosition: CameraPosition(
target: LatLng(currentLocation.latitude,
currentLocation.longitude),
zoom: 12),
markers: markers,
)
: Center(
child: Text('Loading... Please wait...',
style: TextStyle(fontSize: 20.0)),
)),
Then I call this function in the initState to grab my markers:
chargePoints() {
_database.collection('charge_points').getDocuments().then((docs) {
if (docs.documents.isNotEmpty) {
for (int i = 0; i < docs.documents.length; i++) {
initMarker(docs.documents[i].data, docs.documents[i].documentID);
}
}
});
Finally, the initMarker function adds each marker to the Set marker, taken by the Google Map instance:
void initMarker(chargePoint, documentID) {
var markerIdVal = documentID;
final MarkerId markerId = MarkerId(markerIdVal);
// Creating a new Charge Point Marker
final Marker marker = Marker(
markerId: markerId,
icon: markerIcon,
position: LatLng(chargePoint['location'].latitude,
chargePoint['location'].longitude),
infoWindow: InfoWindow(
title: chargePoint['name'], snippet: chargePoint['type']),
onTap: () {
findBookings(context, chargePoint, documentID);
});
setState(() {
markers.add(marker);
});
So my question is; how can I return this data as a Stream, and provide a listener that updates the respective marker icon, when the "occupied" field has been changed?
Firestore
Map UI
Okay, I got a solution!
I'm now returning a StreamBuilder in the main build Widget that takes a Firestore query to return the details of all markers.
I then use the snapshot provided by the stream to intermittently transform the state of all markers set in the initMarker function above.
Additionally, the markers Set is now a Map. This makes more sense for accessing the markers to perform updates.
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
The markers are managed using their MarkerId, which correlates to the documentID of all results returned in the snapshot.
I don't believe this solution is perfect, but I hope I've helped someone out!
StreamBuilder<QuerySnapshot>(
stream: _servicesObj.getChargePoints(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Text('Loading Points');
}
snapshot.data.documents.forEach((change) {
var markerIdVal = change.documentID;
final MarkerId markerId = MarkerId(markerIdVal);
if (change.data['occupied'] == true) {
markers[markerId] = Marker(
markerId: markerId,
icon: pointOccupiedIcon,
position: LatLng(change.data['location'].latitude,
change.data['location'].longitude),
infoWindow: InfoWindow(
title: change.data['name'],
snippet: change.data['type']),
onTap: () {
findBookings(context, change.data, change.documentID);
});
} else {
markers[markerId] = Marker(
markerId: markerId,
icon: pointAvailableIcon,
position: LatLng(change.data['location'].latitude,
change.data['location'].longitude),
infoWindow: InfoWindow(
title: change.data['name'],
snippet: change.data['type']),
onTap: () {
findBookings(context, change.data, change.documentID);
});
}
});
I'm using Flutter to make a mobile application that uses a map. We decided to use Google map and the plugin for flutter we use is:
google_maps_flutter: ^0.5.7
I understand that adding markers to the map works like this:
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
Marker _marker = new Marker(
icon: BitmapDescriptor.defaultMarker,
markerId: _markerId,
position: LatLng(34.024441,-5.0310968),
infoWindow: InfoWindow(title: "userMarker", snippet: '*'),
);
GoogleMap _map;
#override
void initState(
markers[_markerId] = _marker;
_map = new GoogleMap(
/* other properties irrelevant to this prob */
markers: Set<Marker>.of(_markers.values),
);
);
The above snippet does work, I get to see the marker on the map. But modifying the marker or trying to add another marker like in the snippet below does not work.
FloatingActionButton(
onPressed: () {
setState(() {
_marker = new Marker(
icon: BitmapDescriptor.defaultMarker,
markerId: _markerId,
position: LatLng(currentLocation.latitude, currentLocation.longitude),
infoWindow: InfoWindow(title: "userMarker", snippet: '*'),
onTap: () {
debugPrint("Marker Tapped");
},
);
markers[_markerId] = _marker; // What I do here is modify the only marker in the Map.
});
markers.forEach((id,marker) { // This is used to see if the marker properties did change, and they did.
debugPrint("MarkerId: $id");
debugPrint("Marker: [${marker.position.latitude},${marker.position.longitude}]");
});
});
)
My intention here is using another plugin (geoLocator) to get location data of the user and change the only marker I have so it can track his movements. The debugPrint shows that the data is indeed changing, but I see no change in the map (the initial marker that I change uses a different location than my own when I test).
If there's no specific reason for you to use Map data structure, here's what I've done in the past.
I have a Set of Marker in my State
Set<Marker> markers = Set();
Give it to the map widget. markers: markers
GoogleMap(
onMapCreated: _onMapCreated,
myLocationEnabled: true,
initialCameraPosition:
CameraPosition(target: LatLng(0.0, 0.0)),
markers: markers,
)
And then adding the Marker, which I'm building with search result and which you'll be building with your user's location, to Set of Marker in setState method.
// Create a new marker
Marker resultMarker = Marker(
markerId: MarkerId(responseResult.name),
infoWindow: InfoWindow(
title: "${responseResult.name}",
snippet: "${responseResult.types?.first}"),
position: LatLng(responseResult.geometry.location.lat,
responseResult.geometry.location.lng),
);
// Add it to Set
markers.add(resultMarker);
Edit: I've just noticed you're using GoogleMap widget in your initState, you need to move it to the build method if you want to rebuild it everytime with the new state values.
I need to create a button which is going to show me the current location of the user. That's why I use Google Maps, which have the options such this one. But, I need to customize the MyLocation Button but don't know how to do it. Could you please help me with this?
I am pretty new in Flutter though :D
I couldn't find easy way of doing it, but since everything is widget in flutter, you can put your google maps in your stack, and add iconbutton or whatever custom button you need to your stack.
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition:
CameraPosition(target: LatLng(0.0, 0.0)),
markers: markers,
),
IconButton(
icon: Icon(Icons.battery_charging_full),
onPressed: () async {
final center = await getUserLocation();
getNearbyPlaces(center);
Marker myPosition = Marker(
markerId: MarkerId('myLocation'),
position: center == null
? LatLng(0, 0)
: LatLng(center.latitude, center.longitude),
icon: BitmapDescriptor.fromAsset(
'assets/logo.png'));
setState(() {
markers.add(myPosition);
});
},
),
],
)
So what I'm doing here is basicly,
I have Stack which helps me put a IconButton over GoogleMap. When user presssed on that button, I add a new Marker to show current position, There is a Set of Markers on my State, called markers, I'm creating a new Marker by getting the current location of the user, and adding a custom icon to that marker, and then add it to my markers(Set), to display it on GoogleMap.
my getUserLocation function:
Future<LatLng> getUserLocation() async {
LocationManager.LocationData currentLocation;
final location = LocationManager.Location();
try {
currentLocation = await location.getLocation();
final lat = currentLocation.latitude;
final lng = currentLocation.longitude;
final center = LatLng(lat, lng);
return center;
} on Exception {
currentLocation = null;
return null;
}
}
I have location: ^2.1.0 package and using it as LocationManager import 'package:location/location.dart' as LocationManager;
mapController.addMarker(
MarkerOptions(
position: LatLng(37.4219999, -122.0862462),
),
);
I've seen this code snippet in a blog post, and I'm trying to add markers to Google Maps.
The method 'addMarker' isn't defined for the class 'GoogleMapController'.
I think the library has changed and I want to know what's the new way doing this, I've looked up in the controller.dart and api reference but couldn't figure it out.
I would be happy to see some tutorials and blog posts about it, don't hesitate to share.
Yes, The google maps API has changed and the Marker API is widget based and not based in controller anymore.
By CHANGELOG.md
"Breaking change. Changed the Marker API to be widget based, it was controller based. Also changed the example app to account for the same."
I copy some pieces of code from github app example that I think is important to you
Map<MarkerId, Marker> markers = <MarkerId, Marker>{}; // CLASS MEMBER, MAP OF MARKS
void _add() {
var markerIdVal = MyWayToGenerateId();
final MarkerId markerId = MarkerId(markerIdVal);
// creating a new MARKER
final Marker marker = Marker(
markerId: markerId,
position: LatLng(
center.latitude + sin(_markerIdCounter * pi / 6.0) / 20.0,
center.longitude + cos(_markerIdCounter * pi / 6.0) / 20.0,
),
infoWindow: InfoWindow(title: markerIdVal, snippet: '*'),
onTap: () {
_onMarkerTapped(markerId);
},
);
setState(() {
// adding a new marker to map
markers[markerId] = marker;
});
}
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: const CameraPosition(
target: LatLng(-33.852, 151.211),
zoom: 11.0,
),
// TODO(iskakaushik): Remove this when collection literals makes it to stable.
// https://github.com/flutter/flutter/issues/28312
// ignore: prefer_collection_literals
markers: Set<Marker>.of(markers.values), // YOUR MARKS IN MAP
)
I advise you take a look in example app here. There is updated to new API.
I did below example from google codelabs.
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
LatLng _center = LatLng(9.669111, 80.014007);
onMap created add single static marker
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
final marker = Marker(
markerId: MarkerId('place_name'),
position: LatLng(9.669111, 80.014007),
// icon: BitmapDescriptor.,
infoWindow: InfoWindow(
title: 'title',
snippet: 'address',
),
);
setState(() {
markers[MarkerId('place_name')] = marker;
});
}
google map widget:
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 14.0,
),
markers: markers.values.toSet(),
),
I want to pass related marker id by clicking marker on google map. I am using marker.getId() function to retrieve marker id. But the marker id is not passing along with url. How can i do this? Any Help?
function AddressMap(lat,lang,markerid)
{
var latLng = new google.maps.LatLng(lat,lang);
var marker = new google.maps.Marker({
'map': map,
position: latLng,
'latitude' :lat,
'longitude' :lang,
icon: image,
shadow: shadow,
id: markerid
});
markers.push(marker);
google.maps.event.addListener(marker, 'click', function() {
window.location = "www.cickstart.com/" + marker.getId();
});
}
you can try directly to access the id:
google.maps.event.addListener(marker, 'click', function() {
window.location = "www.cickstart.com/" + marker.id;
});
the best way to do this is add a metadata to marker
var marker = new google.maps.Marker(markerOptions);
marker.metadata = {type: "point", id: 1};
if you have so many marker push the marker to array marker.
You can add any data that you want. and simply call it, set it or get it.
the sample like this one:
markers[0].metadata.id