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.
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))
],
)
],
)
]);
},
),
I have a map in flutter where I have to commute the user to a specific point using directions. The red marker on the map when on pressed automatically shows directions on the bottom right but I want to show an arrow head to the user to click the directions on the bottom right because user may not notice it by themselves: https://imgur.com/a/lv9Xq9T
This is the code snippet :
void getLocation() async {
var location = await currentLocation.getLocation();
currentLocation.onLocationChanged.listen((LocationData loc) {
mapcontroller.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(
target: LatLng(loc.latitude ?? 0.0, loc.longitude ?? 0.0), zoom: 5)));
setState(() {
clat = loc.latitude;
clng = loc.longitude;
_markers.addAll({
Marker(
markerId: const MarkerId('Shopkeeper Position'),
icon: BitmapDescriptor.defaultMarker,
// position: LatLng(20.7708612, 73.7235274))
position: LatLng(
widget.latitude,
widget.longitude,
),
onTap: () {
print("");
print("");
print("Marker pressed");
print("");
print("");
Container(
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Get Directions",
style: GoogleFonts.roboto(
fontSize: 40,
fontWeight: FontWeight.w800,
color: Colors.blue,
),
),
Image.asset(
'assets/arrowHead.gif',
width: 200,
height: 200,
),
],
),
);
},
)
});
});
getPolypoints();
});
}
All i get when I tap on the marker are the print statements. I would want to display the row widget as well. How can i do this ?
You need to move your directions container and show/hide depending on the onTap.
Something like this:
isTapped ?? directionsContainer : Container() // empty container if isTapped is false
Update your onTap: to update state with a boolean:
setState(() {
isTapped = !isTapped;
})
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.
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}';
},
),
),
I'm just starting with Flutter and very new to State/Stream/BloC concepts. I'm trying to update a FlutterMap center based on the coordinates from a Geolocator()'s Position stream. At the moment I'm just calling setState() updating a variable with the new value, but next I'll be trying using the Bloc pattern instead..
Now, as well as I set the center on the coordinates of the Position coming from the stream I also set a Marker on the same coordinates. I was expecting to see a Steady marker in the center of the screen and a moving map underneath but is the opposite.. the Map is steady and the Icon is moving.. Can you see where I got it wrong?
Also, for the stream: property of the StreamBuilder how would I get to pass the stream from Geolocator() as an event?
Many thanks for your time and help.
This is the Stream:
StreamSubscription positionStream = _geolocator
.getPositionStream(locationOptions)
.listen((Position position) {
setState(() {
_position = position;
});
print(
_position.latitude.toString() + ',' + _position.longitude.toString()); // ok
});
And this is the Map and the Marker:
Container(
height: 670,
width: 370,
child: FlutterMap(
options: MapOptions(
center: LatLng(_position.latitude, _position.longitude),
minZoom: 16.0,
maxZoom: 19.0,
),
layers: [
TileLayerOptions(
// urlTemplate:
// 'https://api.openrouteservice.org/mapsurfer/{z}/{x}/{y}.png?api_key=omitted',
urlTemplate:
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: ['a', 'b', 'c'],
keepBuffer: 20),
new MarkerLayerOptions(
markers: [
new Marker(
point: new LatLng(
_position.latitude, _position.longitude),
height: 200,
width: 200,
builder: (context) => IconButton(
icon: Icon(Icons.location_on),
color: Colors.red,
iconSize: 60,
onPressed: () {
print('icon tapped');
},
)),
],
),
],
),
),
Found the problem. I didn't assign any MapController().
So I created one and assign it to the FlutterMap. Inside the setState() I added _controller.move(LatLng(_position.latitude, _position.longitude), 16.0); and now the behaviour is the expected one. Steady Icon in the center of the screen and a moving map underneath.
Hope this will help others.
But still I will try to achieve the same with a BLoC pattern.
Cheers