I´m trying to iterate markers in new google flutter map.
I retrieve the array of the coordinates with a web service, then i iterate the elements and get the index that have latitude and longitude.
for (int i = 0; i < list.length; i++) {
mapController.addMarker(MarkerOptions(position: list[0].values.elementAt(i)))));
}
And the map options.
GoogleMapController mapController;
GoogleMap(
onMapCreated: (GoogleMapController mapController) {
mapController = mapController;
},
options: GoogleMapOptions(
mapType: MapType.satellite,
myLocationEnabled :true,
cameraPosition: CameraPosition(
target: LatLng(40.347022, -3.750381), zoom: 5.0),
),
),
I suppose that mapController should take the coordinates that i put in the for loop, but doesn't work. The console return
The method 'addMarker' was called on null.
So the question is, how can i add multiple markers dynamically using google flutter map package?
Also i tried this simple code and works, so the error is occurred when adding markers.
GoogleMapController mapController;
GoogleMap(
onMapCreated: (GoogleMapController mapController) {
mapController = mapController;
mapController.addMarker(MarkerOptions(
position:LatLng(40.347022, -3.750381),
infoWindowText: InfoWindowText("Title", "Content"),
//icon:
));
mapController.addMarker(MarkerOptions(
position:LatLng(43.321871, -3.006887),
infoWindowText: InfoWindowText("Title", "Content"),
//icon:
));
},
options: GoogleMapOptions(
mapType: MapType.satellite,
myLocationEnabled :true,
cameraPosition: CameraPosition(
target: LatLng(40.347022, -3.750381), zoom: 5.0),
),
),
UPDATE 2
I found this example code. This is exactly that i want but i can´t repeat this code, return this error
https://github.com/gerryhigh/Flutter-Google-Maps-Demo/blob/master/lib/venues.dart
NoSuchMethodError: The getter 'className' was called on null.
I call an instance of Google maps in the main build function.Like this:
return GoogleMap(
onMapCreated: _onMapCreated,
options: GoogleMapOptions(
cameraPosition: CameraPosition(
target: _center1,
zoom: 11.0,
),
),
);
Inside the "_onMapCreated" function is where I have the iterator:
widget.model.allItems.forEach((item) {
//print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
print(item.lat);
var newItem = LatLng(double.parse(item.lat), double.parse(item.lon));
mapController.addMarker(
MarkerOptions(
icon: BitmapDescriptor.fromAsset(assetName),
position: newItem,
),
);
});
This is working for me.
In the first example GoogleMapController paramater and your local variable have the same name, so basically, local variable becomes shadowed and you're assigning function parameter value to itself. Renaming one of these two should resolve the issue.
void populateOrder(Item item) async {
if (item != null) {
for (int i = 0; i < item.feature.length; i++) {
var position = item.feature[i];
if (position != null) {
try {
if (double.parse(position.latitude) != null &&
double.parse(position.longitude) != null) {
mapController.clearMarkers().then((value){
mapController.addMarker(
MarkerOptions(
position: LatLng(double.parse(position.latitude),
double.parse(position.longitude)),
infoWindowText: InfoWindowText(position.schet, ""),
icon: BitmapDescriptor.defaultMarker,
),
);
});
}
} catch (e) {
print(e);
}
}
}
}
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
populateOrder(itemize);
Future.delayed(Duration(seconds: 6));
}
The library was updated: this is how I was able to show multiple markers on the map.
Completer<GoogleMapController> _controller = Completer();
// initial camera position
CameraPosition _cameraPos;
// A map of markers
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
// function to generate random ids
int generateIds() {
var rng = new Random();
var randomInt;
randomInt = rng.nextInt(100);
print(rng.nextInt(100));
return randomInt;
}
//call this function in initstate
// I'm getting a json Object with locations from an
// external api
buildMarkers() {
for (var i = 0; i < gridItem.locations.length; i++) {
var markerIdVal = generateIds();
final MarkerId markerId = MarkerId(markerIdVal.toString());
final Marker marker = Marker(
markerId: markerId,
position: LatLng(
gridItem.locations[i].latitude,
gridItem.locations[i].longitude,
),
infoWindow: InfoWindow(title: gridItem.locations[i].place, snippet: gridItem.locations[i].region),
);
// you could do setState here when adding the markers to the Map
markers[markerId] = marker;
}
print("Length:: + ${markers.length}");
}
// your Googlemaps Widget somewhere in your widget tree
GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _cameraPos,
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>[Factory<OneSequenceGestureRecognizer>(()=>ScaleGestureRecognizer())].toSet(),
markers: Set<Marker>.of(markers.values),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);}),
Related
After two geolocation updates, it crashes and doesn't follow me in the map:
StreamSubscription subscription;
super.initState();
subscription = getPositionStream(desiredAccuracy: LocationAccuracy.high, distanceFilter: 10).listen(
(Position position) async {
getLocation();
centerScreen(position);
print(position == null ? 'Unknown' : position.latitude.toString() + ', ' + position.longitude.toString());
});
}
just to be safe, i tried adding: subscription.resume() to my _onMapCreated (flutter google maps). No impact...
Here's my getLocation:
Future getLocation() async {
Position position =
await getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
lat = position.latitude;
lng = position.longitude;
setState(() {});
}
and my center screen function:
Future<void> centerScreen(Position position) async {
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(
target: LatLng(position.latitude, position.longitude),
zoom: _currentZoom)));
}
This is with the latest release of flutter geolocator and flutter google maps.
I've been trying to figure this out for two days... I would really appreciate your help. Thank you in advance.
Took it out of my init state. Passed it to getLocation like so:
Future getLocation() async {
subscription = getPositionStream(desiredAccuracy: LocationAccuracy.high, distanceFilter: 10).listen(
(Position position) async {
final GoogleMapController controller = await _controller.future;
// final GoogleMapController currentZoom = await _controller.zoom;
controller.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(
target: LatLng(position.latitude, position.longitude),
zoom: _currentZoom)));
});
works well.
GoogleMapFlutter with Geolocator
// GoogleMapFlutter with Geolocator
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
class Map extends StatefulWidget {
#override
_MapState createState() => _MapState();
}
class _MapState extends State<Map> {
bool mapToggle = false;
var currentLocation;
#override
//initiate position
void initState() {
super.initState();
//Geolocation
Geolocator.getCurrentPosition().then((currloc) {
setState(() {
currentLocation = currloc;
mapToggle = true;
});
});
}
//Location Marker
Set<Marker> _createMarker() {
return <Marker>[
Marker(
markerId: MarkerId("currentLocation"),
position: LatLng(currentLocation.latitude, currentLocation.longitude),
icon: BitmapDescriptor.defaultMarker,
infoWindow: InfoWindow(title: "Your Location"),
)
].toSet();
}
#override
Widget build(BuildContext context) {
return Stack(
children: [
mapToggle
//Google Map flutter
? GoogleMap(
mapType: MapType.normal,
markers: _createMarker(),
initialCameraPosition: CameraPosition(
target: LatLng(
currentLocation.latitude, currentLocation.longitude),
zoom: 15.0))
//Loading
: Center(
child: Text(
'Loading.. Please wait..',
style: TextStyle(fontSize: 20.0),
)),
],
);
}
}
I have created a customised image to use as my marker icon for one of my markers on google maps on my flutter app. Unfortunately, this is not working as planned and the default icon is being displayed instead. Can anybody spot the eroor? I certainly can't. As a side note, nothing in my if statements is being printed in the console. An issue for another day?
This is the code I used to get up my marker:
var map;
var rmarker;
final restaurantmarker = BitmapDescriptor.fromAssetImage(
ImageConfiguration(), 'assets/images/yellow_MarkerR.png')
.then((value) => rmarker = value);
final mapp = location.getLocation().then((value) => map = value);
final _markers = [
Marker(
markerId: MarkerId("my_location"),
position: LatLng(41.16599, -110.75792),
infoWindow: InfoWindow(title: "YOUR HOME"),
),
Marker(
markerId: MarkerId("RESTAURANT"),
icon: rmarker,
position: LatLng(40.16599, -110.75792),
infoWindow: InfoWindow(title: "Restaurant"))
];
final setmarkers = _markers.toSet();
class NearbyScreen extends StatelessWidget {
void initState() {
startService();
}
#override
//LocationHelper.mapviewpointer(latitude: )
Widget build(BuildContext context) {
return /* !_serviceEnabled ? Center(child:Text("Page cannot be viewed"),) :
map == null
? Center(
child: Text("Null response"),
)
:*/
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(41.16599,
-110.75792 /*map.latitude, map.longitude
double.parse(coordinates[0]), double.parse(coordinates[1]) */
)),
//minMaxZoomPreference: MinMaxZoomPreference(10, 20),
zoomControlsEnabled: true,
markers: setmarkers,
);
}
}
And this is the full code:
Future<bool> assignService(Location loc) async {
bool servicestatus = await loc.serviceEnabled();
print("Service status $servicestatus");
return servicestatus;
}
Future<PermissionStatus> assignPermission(Location loc) async {
var hasPermission = await loc.hasPermission();
print("Permission status $hasPermission");
return hasPermission;
}
Location location = Location();
var _serviceEnabled;
var _serve = assignService(location).then((value) => _serviceEnabled = value);
//var _permissionGranted = assignPermission(location);
var _permissionGranted;
var _permi =
assignPermission(location).then((value) => _permissionGranted = value);
void startService() {
if (!_serviceEnabled) {
_serviceEnabled = assignService(location);
print("service disabled");
if (!_serviceEnabled) {
return;
}
}
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = assignPermission(location);
print("permission denied");
if (_permissionGranted != PermissionStatus.granted) {
return;
}
}
}
var map;
var rmarker;
final restaurantmarker = BitmapDescriptor.fromAssetImage(
ImageConfiguration(), 'assets/images/yellow_MarkerR.png')
.then((value) => rmarker = value);
final mapp = location.getLocation().then((value) => map = value);
final _markers = [
Marker(
markerId: MarkerId("my_location"),
position: LatLng(41.16599, -110.75792),
infoWindow: InfoWindow(title: "YOUR HOME"),
),
Marker(
markerId: MarkerId("RESTAURANT"),
icon: rmarker,
position: LatLng(40.16599, -110.75792),
infoWindow: InfoWindow(title: "Restaurant"))
];
final setmarkers = _markers.toSet();
class NearbyScreen extends StatelessWidget {
void initState() {
startService();
}
#override
//LocationHelper.mapviewpointer(latitude: )
Widget build(BuildContext context) {
return /* !_serviceEnabled ? Center(child:Text("Page cannot be viewed"),) :
map == null
? Center(
child: Text("Null response"),
)
:*/
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(41.16599,
-110.75792 /*map.latitude, map.longitude
double.parse(coordinates[0]), double.parse(coordinates[1]) */
)),
//minMaxZoomPreference: MinMaxZoomPreference(10, 20),
zoomControlsEnabled: true,
markers: setmarkers,
);
}
}
I am also getting an error in my terminal that says: E/Parcel (22617): Reading a NULL string not supported here.
E/Parcel (22617): Reading a NULL string not supported here.
Looks like you are not retrieving the marker icon on your code properly as you only define it as restaurantmarker. Here is how you can resolve this:
First, you need to make sure that you have define your icon on your pubspec.yaml under Flutter: section:
Flutter:
assets:
- assets/images/yellow_MarkerR.png
Then, you will need to call the BitmapDescriptor.fromAssetImage inside initState() to get the icon before the map loads:
void initState() {
BitmapDescriptor.fromAssetImage(
ImageConfiguration(), 'assets/images/yellow_MarkerR.png')
.then((value) => rmarker = value);
}
There are many issues with your code and I just refactored the important part of your code for maps logic.
But the important issue is that you are not insuring the initialization of restaurantMarker. I added a check for that here which isSetupReady;
First, make sure you have added icon assets assets/images/yellow_MarkerR.png into your pubsepc.yaml file.
import 'package:flutter/material.dart';
class NearbyScreen extends StatefulWidget {
#override
_NearbyScreenState createState() => _NearbyScreenState();
}
class _NearbyScreenState extends State<NearbyScreen> {
var _markers;
var setmarkers;
var restaurantMarker;
bool isSetupReady = false;
#override
void initState() {
doSetup();
super.initState();
}
doSetup() async {
restaurantMarker = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(), 'assets/images/yellow_MarkerR.png');
_markers = [
Marker(
markerId: MarkerId("my_location"),
position: LatLng(41.16599, -110.75792),
infoWindow: InfoWindow(title: "YOUR HOME"),
),
Marker(
markerId: MarkerId("RESTAURANT"),
icon: rmarker,
position: LatLng(40.16599, -110.75792),
infoWindow: InfoWindow(title: "Restaurant"))
];
setmarkers = _markers.toSet();
setState(() {
isSetupReady = true;
});
}
#override
//LocationHelper.mapviewpointer(latitude: )
Widget build(BuildContext context) {
return /* !_serviceEnabled ? Center(child:Text("Page cannot be viewed"),) :
map == null
? Center(
child: Text("Null response"),
)
:*/
isSetupReady
? GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(41.16599,
-110.75792 /*map.latitude, map.longitude
double.parse(coordinates[0]), double.parse(coordinates[1]) */
)),
//minMaxZoomPreference: MinMaxZoomPreference(10, 20),
zoomControlsEnabled: true,
markers: setmarkers,
)
: Center(child: Text('Loading Maps...'));
}
}
I am using Flutter and the Google Maps API.
I have managed to have a custom marker that is displayed when the map opens.
Is there a way to have multiple different custom markers Images at the same time on the same map?
I can't find a way to do that.
Any ideas or links are welcomed :)
class Neighborhood extends StatefulWidget {
const Neighborhood({Key key}) : super(key: key);
#override
_NeighborhoodState createState() => _NeighborhoodState();
}
class _NeighborhoodState extends State<Neighborhood> {
Location _location = Location();
GoogleMapController _controller;
List<Marker> allMarkers = [];
PageController _pageController;
int prevPage;
int bottomSelectedIndex = 0;
//initialising the custom pinIcon
BitmapDescriptor pinIcon;
#override
void initState() {
super.initState();
//calling the the function that will await the pinIcon and have it ready with initState();
setCustomMapPin();
_pageController = PageController(initialPage: 1, viewportFraction: 0.8)
..addListener(_onScroll);
}
void _onScroll() {...
_myPlacesList(index) {...
Then I created the Google Map
child: GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(40.505757, 22.846576),
zoom: 12.0,
),
onMapCreated: mapCreated,
myLocationEnabled: true,
myLocationButtonEnabled: true,
mapToolbarEnabled: false,
markers: Set.from(allMarkers),
),
),
}
void setCustomMapPin() async {
pinIcon = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(devicePixelRatio: 2.5), 'assets/images/iconMap.png');
}
void mapCreated(controller) {
setState(() {
_controller = controller;
_location.getLocation();
//Adding markers to the screen.Calling the markers from different file.
myPlaces.forEach((e) {
allMarkers.add(Marker(
markerId: MarkerId(e.name),
draggable: false,
icon: pinIcon,
infoWindow: InfoWindow(
title: e.name,
snippet: e.address,
),
position: e.locationCoords,
onTap: () {
_pageController.animateToPage(myPlaces.indexOf(e),
duration: Duration(milliseconds: 300), curve: Curves.ease);
},
));
});
});
}
//moves the camera to pin location
void moveCamera() {...
}
You can do it with something like this
_markers.add(Marker(
consumeTapEvents: true,
position: _center,
infoWindow: InfoWindow(
title: 'New Marker',
snippet: '',
),
icon: markerImage, //you custom marker, instance of BitmapDescriptor
)
and than you instantiate the map with:
GoogleMap(
onMapCreated: (GoogleMapController controller) {
mapController = controller;
},
myLocationEnabled: locationEnable,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 10.0,
),
mapType: MapType.normal,
markers: _markers,
)
var markerImage = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(size: Size(96, 96)),
'assets/image/marker_image.png');
I am using Google Maps within my Flutter project. I am trying to parse two JSON files in my assets so that I can use their latitudes and longitudes in a Polyline and markers. The markers work fine but now I am adding another future to my Future builder for the polylines and I receive the following error:
The argument type LatLng can't be assigned to the parameter type List<LatLng>.
Future _future;
Future _futuree;
Future<String> loadString() async => await rootBundle.loadString('assets/busStops/stops_${widget.selectStation}.json');
List<Marker> allMarkers = [];
GoogleMapController _controller;
#override
void initState() {
// TODO: implement initState
super.initState();
//future 1
_future = loadString();
//future 2
_futuree = loadMyCoord();
}
Future<String> loadMyCoord() async {
var x = await rootBundle
.loadString('assets/route/coords_Centurion.json');
return x;
}
#override
Widget build(BuildContext context) {
createMarker(context);
return Scaffold(
appBar: AppBar(
title: Text("Bus Routes"),
centerTitle: true,
backgroundColor: Color.fromRGBO(59, 62, 64, 1),
actions: <Widget>[
FlatButton(
textColor: Colors.white,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => busStationList()),
);
},
child: Icon(Icons.add),
),
],
),
body: Stack(children: [
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: FutureBuilder(
// Futures
future: Future.wait(
[
//[0]
_future,
//[1]
_futuree,
]
),
builder: (
context,
AsyncSnapshot<List<dynamic>> snapshot,
) {
// Check hasData once for all futures.
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
List<dynamic> parsedJson = jsonDecode(snapshot.data[0]);
allMarkers = parsedJson.map((element) {
return Marker(
icon: customIcon,
markerId: MarkerId(element["Latitude"].toString()),
position: LatLng(element['Latitude'] ?? 0.0,
element['Longitude'] ?? 0.0));
}).toList();
List<dynamic> parseJson = jsonDecode(snapshot.data[1]);
List<Polyline> allPolylinesByPosition = [];
parseJson.forEach((element){
List<dynamic> coords = element["coords"];
coords.forEach((i) {
double lat = double.tryParse(i["latitude"]);
double lng = double.tryParse(i["longitude"]);
allPolylinesByPosition.add(Polyline(
polylineId: PolylineId('lines'),
points: points: LatLng(lat ?? 0.0, lng ?? 0.0);
visible: true,
color: Colors.red
));
}
);
});
return GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(-26.1711459, 27.9002758), zoom: 9.0),
markers: Set.from(allMarkers),
onMapCreated: mapCreated,
polylines: Set.from(allPolylinesByPosition),
);
},
),
),
]),
);
}
void mapCreated(controller) {
setState(() {
_controller = controller;
});
}
Few things to note, points parameter of Polyline only accepts list of LatLng (List<LatLng>) and not LatLng.
This line should be changed in your code. Try adding a list of LatLng instead of passing a single LatLng instance in the points parameter.
points: LatLng(lat ?? 0.0, lng ?? 0.0);
Polyline.dart
class Polyline {
const Polyline({
#required this.polylineId,
this.consumeTapEvents = false,
this.color = Colors.black,
this.endCap = Cap.buttCap,
this.geodesic = false,
this.jointType = JointType.mitered,
this.points = const <LatLng>[],
this.patterns = const <PatternItem>[],
this.startCap = Cap.buttCap,
this.visible = true,
this.width = 10,
this.zIndex = 0,
this.onTap,
});
Hi I have now done the following , and pulling data but it is not showing on the map
List<dynamic> parseJson = jsonDecode(snapshot.data[1]);
Set<Polyline> allPolylinesByPosition = {};
parseJson.forEach((element) {
List<dynamic> coords = element["coords"];
coords.forEach((i) {
List<LatLng> latlng = [
LatLng( double.tryParse(i["latitude"]) ?? 0.0 ,double.tryParse(i["longitude"]) ?? 0.0)
];
allPolylinesByPosition.add(Polyline(
polylineId: PolylineId((_lastMapPosition.toString())),
points:latlng,
visible: true,
width: 4,
color: Colors.red
));
print(PolylineId);
}
);
});
return GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(-26.1711459, 27.9002758), zoom: 2.0),
markers: Set.from(allMarkers),
onMapCreated: mapCreated,
polylines: allPolylinesByPosition,
);
},
),
'''
how can we setup initial camera positions in googleMap i.e. instead of hard code lat/lang (below code)
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(30.666, 76.8127),
zoom: 15
),
onMapCreated: _onMapCreated,
myLocationEnabled: true,
mapType: MapType.hybrid,
compassEnabled: true,
trackCameraPosition: true,
)
I just want my current location lat/lang instead of hard coded values
Use location package.
Here is an example.
var currentLocation = LocationData;
var location = new Location();
// Platform messages may fail, so we use a try/catch PlatformException.
try {
currentLocation = await location.getLocation();
} on PlatformException catch (e) {
if (e.code == 'PERMISSION_DENIED') {
error = 'Permission denied';
}
currentLocation = null;
}
And then
var location = new Location(); location.onLocationChanged().listen((LocationData currentLocation) {
print(currentLocation.latitude);
print(currentLocation.longitude);
})