I'm creating simple app, and I need that when the map is tapped a marker should be added. I'm using the onTap property of the google_maps_flutter plugin:
var markers = Set<Marker>();
...
body: Stack(
children: [
Positioned.fill(
child: GoogleMap(
onTap: (LatLng point) {
print(point.longitude.toString());
final snackBar = SnackBar(
content: Text(point.longitude.toString()),
action: SnackBarAction(
label: 'Undo',
onPressed: () {
// Blah.
},
),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
setState(() {
markers.add(Marker(
markerId: MarkerId(point.toString()),
position: point,
infoWindow: InfoWindow(
title: 'I am a marker in ${point}',
),
icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueMagenta),
anchor: Offset(100, 160),
));
});
},
//--
myLocationEnabled: true,
zoomControlsEnabled: false,
markers: markers,
initialCameraPosition: CameraPosition(
target: currentLocation,
),
onMapCreated: (GoogleMapController controller) {
_mapController.complete(controller);
},
),
),
...
I added a print and a snackbar just to make sure I was getting the location information, and works just fine. I don't get any errors anywhere. I also added the map directly into the body (no Stack), and still doesn't do anything. I'm not sure what's happening. I can add more portions of then code if needed.
Related
I am trying to make a moving google map marker according to the user location, I use the geolocator listen function from the geolocator pub dev. The position of the markers got updated however the marker did not show up on the google map at all I tried using setState(){} to refresh the map, however nothing change.
Here's the function that I use
void listenToLocation()
{
Position? userposition;
final LocationSettings _locationSettings = LocationSettings(accuracy: LocationAccuracy.high,distanceFilter: 100);
userStreamlocation = Geolocator.getPositionStream(locationSettings: _locationSettings).listen(
(userposition) {
print(userposition == null ? 'Unknown' : '${userposition.latitude.toString()}, ${userposition.longitude.toString()}');
useablepos=LatLng(userposition.latitude, userposition.latitude);
_Navmarkers.remove(UserMarker);
print('USABLE POSITION:' + useablepos.toString());
UserMarker = Marker(
markerId: MarkerId('User'),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueCyan),
position: useablepos,
draggable: true,);
_Navmarkers.add(UserMarker);
setState(){};
print('User Location :' + UserMarker.position.toString());
});
}
I am able to remove the user marker and replace it with a new marker that have the new position however the marker did not show up on the googlemap
Here's the image to show that the LatLng keep getting updated,
Edit: UI Screenshot, there is only a single button that function to start the listen function
Update: I tried several thing and the only thing I found out is that the listen run outside the map state, I still have no idea what to do
I am able to fix this after finding out that the marker didn't got updated because it is in a different state than the main widget, I fix it trough the use of the statebuilder widget. Apparently without statefulbuilder, the setState refresh the whole app but not what the function do. here's the code snip
StatefulBuilder(
builder: (context, setMapState) {
setMapState(
() {},
);
void _whenMapCreated(GoogleMapController controller) async {
//debugPrint('>>>>>>>>> onMapCreated');
mapController = controller;
_Navmarkers.clear();
_navPolylines.clear();
var direction =
await LocationService().getDirectionNoWP(userOrigin, userGoal);
_setPolylines(direction['polyline_decoded']);
setMapState(
() {},
);
}
return Column(children: [
Expanded(
child: GoogleMap(
mapType: MapType.normal,
initialCameraPosition:
CameraPosition(target: _kGooglePlex, zoom: 11),
markers: _Navmarkers,
polylines: _navPolylines,
onMapCreated: _whenMapCreated,
)),
Row(
children: [
ButtonBar(
children: [
IconButton(
onPressed: () {
Position? userposition;
const LocationSettings _locationSettings =
LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 100,
);
userStreamlocation = Geolocator.getPositionStream(
locationSettings: _locationSettings)
.listen((userposition) {
_Navmarkers.clear();
_Navmarkers.add(Marker(
markerId: MarkerId('User'),
position: LatLng(userposition.latitude,
userposition.longitude),
icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueRose)));
setMapState(() {
});
});
},
icon: Icon(Icons.navigation)),
IconButton(
onPressed: () {
setMapState(
() {
},
);
},
icon: Icon(Icons.refresh)),
IconButton(
onPressed: () {
dispose();
},
icon: Icon(Icons.stop))
],
)
],
)
]);
},
),
In Flutter, I created an array to add markers.
final List<Marker> _markers = <Marker>[];
Then I iterate all values and add them to this array
UserService().getAll().then((value) {
setState(() {
for (var element in value) {
_markers.add(Marker(
markerId: MarkerId(element.id.toString()),
position: LatLng((element.latitude), element.longitude),
infoWindow: InfoWindow(
title: element.name,
),
icon: BitmapDescriptor.defaultMarker,
));
}
});
}).catchError((e) {
debugPrint(e);
});
Finally on Google Maps i add this array to markers
final map = GoogleMap(
myLocationEnabled: true,
zoomControlsEnabled: false,
onMapCreated: _onMapCreated,
markers: _markers.map((e) => e).toSet(),
initialCameraPosition: CameraPosition(
target: _center,
zoom: 8.0,
),
);
The problem: Map only shows the first element of this array in the map. Does anybody know what´s wrong?
I have a compass plugin that is giving direction angle, and also location plugin that provide the current location. With these plugins, I use google maps placed under Streambuilder to put my current location as marker and with a line to another location.
The issue I am facing currently is how to rotate the map automatically when the device is rotated, as the first plugin provides direction angle (double value) that gets updated streams as the device rotate.
I wanted to use this angle value to update Google Maps bearing automatically, so that the map rotates accordingly.
I have tired many ways but of no use. Google maps does not respond.
this is my code:
Completer<GoogleMapController> _controller = Completer();
return StreamBuilder(
stream: FlutterQiblah.qiblahStream,
builder: (_, AsyncSnapshot<QiblahDirection> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) return LoadingIndicator();
final qiblahDirection = snapshot.data;
_goToTheLake(qiblahDirection);
return GoogleMap(
mapType: MapType.satellite,
zoomGesturesEnabled: true,
compassEnabled: true,
myLocationEnabled: false,
myLocationButtonEnabled: true,
rotateGesturesEnabled: true,
initialCameraPosition: CameraPosition(
target: position,
zoom: 18,
// bearing: qiblahDirection.direction,
),
markers: Set<Marker>.of(
<Marker>[
widget.meccaMarker,
Marker(
draggable: true,
markerId: MarkerId('Marker'),
position: position,
icon: BitmapDescriptor.defaultMarker,
rotation: qiblahDirection.qiblah,
onTap: () {
_goToTheLake(qiblahDirection);
},
onDragEnd: (LatLng value) {
position = value;
_positionStream.sink.add(value);
},
zIndex: 5,
),
],
),
circles: Set<Circle>.of([
Circle(
circleId: CircleId("Circle"),
radius: 10,
center: position,
fillColor: Theme.of(context).primaryColorLight.withAlpha(100),
strokeWidth: 1,
strokeColor: Theme.of(context).primaryColorDark.withAlpha(100),
zIndex: 3,
)
]),
polylines: Set<Polyline>.of([
Polyline(
polylineId: PolylineId("Line"),
points: [position, QiblahMaps.LatLong],
color: Theme.of(context).primaryColor,
width: 5,
zIndex: 4,
)
]),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
);
},
)
I have placed this function as future called from inside stream builder in order to change the "bearing" of the map:
final GoogleMapController controller = await _controller.future;
controller.moveCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
bearing: qiblahDirection.direction,
),
),
);
} ```
Try this plugin flutter_compass
use the events to update google map bearing as you wish
I'm using google map picker. But appearing problem when I select place
RangeError (RangeError (index): Invalid value: Valid value range is empty: 0)
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () async {
LocationResult result = await showLocationPicker(
context,
"blablablagooglekey",
initialCenter: LatLng(41.2995, 69.2401),
myLocationButtonEnabled: true,
layersButtonEnabled: true,
desiredAccuracy: LocationAccuracy.best,
);
print("result = $result");
setState(() => _pickedLocation = result);
},
child: Text('Pick location'),
),
Text(_pickedLocation.toString() ?? 'Test'),
],
),
);
How can I fix this?
I need select place for meeting buttun.
If you trying to achieve map picker, try this package:
https://pub.dev/packages/map_picker.
MapPicker(
// pass icon widget
iconWidget: SvgPicture.asset(
"assets/location_icon.svg",
height: 60,
),
//add map picker controller
mapPickerController: mapPickerController,
child: GoogleMap(
myLocationEnabled: true,
zoomControlsEnabled: false,
// hide location button
myLocationButtonEnabled: false,
mapType: MapType.normal,
// camera position
initialCameraPosition: cameraPosition,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
onCameraMoveStarted: () {
// notify map is moving
mapPickerController.mapMoving!();
textController.text = "checking ...";
},
onCameraMove: (cameraPosition) {
this.cameraPosition = cameraPosition;
},
onCameraIdle: () async {
// notify map stopped moving
mapPickerController.mapFinishedMoving!();
//get address name from camera position
List<Placemark> placemarks = await placemarkFromCoordinates(
cameraPosition.target.latitude,
cameraPosition.target.longitude,
);
// update the ui with the address
textController.text =
'${placemarks.first.name}, ${placemarks.first.administrativeArea}, ${placemarks.first.country}';
},
),
),
along with greeting you, I wanted to ask you if someone has been able to show an InfoWindow in the flutter map maker, or create a container that is floating so that it appears next to the maker, in google map if possible.
new Marker
(
width: 45.0,
height: 45.0,
point: new LatLng(-25.963678, -51.240657),
builder: (ctx) =>
new Container //here infoWindow or Float Container
(
//child: new FlutterLogo(),
child: IconButton
(
icon: Icon(Icons.location_on),
color: Colors.blue,
iconSize: 45.0,
tooltip: "prueba",
onPressed: ()
{
print("test press");
},
)
),
),
Thank you very much for the help as always.
You cannot set a widget as the marker info-window in any of the flutter map plugins. You can only set the title and text of the info-window in the google maps plugins.
You could turn the map info-window off, center the map on the marker if the user clicks on it, and add some code to show a custom dialog at the approximate center of the screen. You would have to use the flutter Stack widget.
Stack(
children:[
Map(
markers: [Marker(/*no info-window*/, onTap: (){
setState((){ _opacity = 1; });
})],
onMapMove: (){
setState((){ _opacity = 0; });
}
),
Opacity(
opacity: _opacity,
child: /*custom info-window*/,
),
],
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
),
Use custom_info_window package as follows:
Step 1: Initialise CustomInfoWindowController.
CustomInfoWindowController _customInfoWindowController = CustomInfoWindowController();
Step 2: Call CustomInfoWindowController's addInfoWindow from marker's onTap function.
Marker(
markerId: MarkerId("marker_id"),
position: _latLng,
onTap: () {
_customInfoWindowController.addInfoWindow(
<YOUR CUSTOM WIDGET>,
_latLng,
);
},
)
Step 3: Use GoogleMap Widget with Stack.
Stack(
children: <Widget>[
GoogleMap(
onTap: (position) {
_customInfoWindowController.hideInfoWindow();
},
onCameraMove: (position) {
_customInfoWindowController.onCameraMove();
},
onMapCreated: (GoogleMapController controller) async {
_customInfoWindowController.googleMapController = controller;
},
markers: _markers,
initialCameraPosition: CameraPosition(
target: _latLng,
zoom: _zoom,
),
),
CustomInfoWindow(
controller: _customInfoWindowController,
height: 75,
width: 150,
offset: 50,
),
],
)
Call _customInfoWindowController.hideInfoWindow(); inside GoogleMap's onTap to hide CustomInfoWindow when clicking on map but not on the marker.
Call _customInfoWindowController.onCameraMove(); to maintain CustomInfoWindow's position relative to marker. [IMPORTANT]
Assign _customInfoWindowController.googleMapController = controller; inside onMapCreated. [IMPORTANT]
Add CustomInfoWindow as next child to float this on top GoogleMap.