Bring modal bottom sheet on clicking a google map marker - google-maps

I want to bring a modal bottom sheet upon clicking a google map marker and display some dynamic data using flutter

You can program the onTap event of the marker to show a modal bottom sheet:
final Marker marker = Marker(
markerId: markerId,
position: LatLng(lat, lon),
onTap: () {
controller.animateCamera(CameraUpdate.newCameraPosition(
new CameraPosition(
target: LatLng(lat, lon), zoom: 18)));
showModalBottomSheet(
context: context,
builder: (builder) {
return Container(
child: _buildBottonNavigationMethod(your_data),
);
});
},
);
And here you build your widget as you want:
Column _buildBottonNavigationMethod(your_data) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: Icon(Icons.ac_unit),
title: Text('Add as favourite'),
)
],
);
}

Related

Flutter - Provide Real-Time Updates to Google Maps Using StreamBuilder

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);
});
}
});

Unable to drag marker on google map in flutter

I'm using google_maps_flutter: ^0.5.24+1 plugin. I can't drag the marker inside map even though draggable property is set true. Whats wrong here? My code :
return GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(placemark.position.latitude,
placemark.position.longitude),
zoom: 18,
),
markers: Set<Marker>.of(
<Marker> [
Marker(
markerId: MarkerId("home"),
position: LatLng(placemark.position.latitude, placemark.position.longitude),
icon: BitmapDescriptor.defaultMarker,
infoWindow: InfoWindow(
title: placemark.name
),
draggable: true,
),
]
),
onMapCreated: (mapController) {
googleMapController = mapController;
},
);
You need to long press the Marker to trigger the drag event. To debug, you can use the onDrag() property to see if the drag event has been started.

Flutter google map not rendering when changing camera position

I am trying to show a Stack widget containing a Google Map on the bottom and an icon (car) on top, in a way that the car should be following the path on the road given by different GPS coordinate positions (lat, lon).
To simulate that, the car icon is always drawn in the center of the Stack and the Google Map is moved under the icon using:
_mapController.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(
newPosition.target.latitude,
newPosition.target.longitude,
),
zoom: 19,
),
));
here is the drawing of the map + the icon:
Widget drawStack() {
return Container(
width: 930,
height: 524,
child: Stack(
children: <Widget>[
_buildGoogleMaps(),
Align(
alignment: Alignment.center,
child: Image.asset("assets/images/carIconMap.png", width: 50, height: 93),
),
],
),
),
],
));
}
Everything works fine at the beginning but as more coordinate points are given, there is a moment (part outside of the Container), when the map seems to not be loaded when the camera is moving.
I have tried to give the map the maximum and minimum lat,lon bounds via the property cameraTargetBounds of the GoogleMap constructor.
But nothing seems to be working.
this worked to me
CameraPosition _initialPosition = CameraPosition(target: _latlng, zoom: 16);
Position currentLocation;
_getLocation() async {
currentLocation = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.best);
var newPosition = CameraPosition(
target: LatLng(currentLocation.latitude, currentLocation.longitude),
zoom: 16);
CameraUpdate update =CameraUpdate.newCameraPosition(newPosition);
CameraUpdate zoom = CameraUpdate.zoomTo(16);
_mapController.moveCamera(update);
}
and this is my widget
GoogleMap(
onMapCreated: onMapCreated,
initialCameraPosition: _initialPosition,
myLocationEnabled: true,
myLocationButtonEnabled: false,
),

Flutter: How to add marker to Google Maps with new Marker API?

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(),
),

Flutter - Drag marker and get new position

In Flutter I have a map that take the device position with help of location. Then i use this position to show marker in Google map with help of Google Maps Flutter plugin.
The code is similar to
child: GoogleMap(
mapType: MapType.hybrid,
initialCameraPosition: CameraPosition(
target: LatLng(lat, lng),
zoom: 5,
),
markers: Set<Marker>.of(
<Marker>[
Marker(
draggable: true,
markerId: MarkerId("1"),
position: LatLng(lat, lng),
icon: BitmapDescriptor.defaultMarker,
infoWindow: const InfoWindow(
title: 'Usted está aquí',
),
)
],
),
onMapCreated: (GoogleMapController controller) {
mapController = controller;
},
))
If location plugin fails or take wrong data i need to have the option to reposition this marker. I use draggable: true to drag marker, but i need to take the new latitude and longitude for save it in database.
So the question is: Using the draggable how can i get the new latitude and longitude?
If you allow me, I would suggest a different approach to this problem. I think in the current version of google maps for Flutter (0.4.0) you don't have a method to get the new position after dragging the marker, so my solution was to use the camera position to move the marker around and then use the current camera position to get the new coordinates.
So in your code, you could do something like this:
child: GoogleMap(
mapType: MapType.hybrid,
initialCameraPosition: CameraPosition(
target: LatLng(lat, lng),
zoom: 5,
),
markers: Set<Marker>.of(
<Marker>[
Marker(
draggable: true,
markerId: MarkerId("1"),
position: LatLng(lat, lng),
icon: BitmapDescriptor.defaultMarker,
infoWindow: const InfoWindow(
title: 'Usted está aquí',
),
)
],
),
onCameraMove: ((_position) => _updatePosition(_position)),
onMapCreated: (GoogleMapController controller) {
mapController = controller;
},
))
Then you can set your marker's new state each time the user moves the camera around and use this coordinates for any other purpose you need:
void _updatePosition(CameraPosition _position) {
Position newMarkerPosition = Position(
latitude: _position.target.latitude,
longitude: _position.target.longitude);
Marker marker = markers["1"];
setState(() {
markers["1"] = marker.copyWith(
positionParam: LatLng(newMarkerPosition.latitude, newMarkerPosition.longitude));
});
}
I hope it helps!
Marker have onDragEnd property. using onDragEnd property give new latitude and longitude.
Marker(
onTap: () {
print('Tapped');
},
draggable: true,
markerId: MarkerId('Marker'),
position: LatLng(value.latitude, value.longitude),
onDragEnd: ((newPosition) {
print(newPosition.latitude);
print(newPosition.longitude);
}))