I need to load maps in background because when I hit the tab with maps.dart for the first time, map is loading. It is looking bad so I want to use FutureBuilder to show CircularProgressIndicator() but I have no idea how to do this.
I know how to do it with Lists but in this case...
This maps.dart code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class Maps extends StatefulWidget {
#override
_MapsState createState() => _MapsState();
}
class _MapsState extends State<Maps> with AutomaticKeepAliveClientMixin {
Completer<GoogleMapController> _controller = Completer();
#override
void initState() {
super.initState();
}
double zoomValue = 9.0;
#override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
body: Stack(
children: <Widget>[
_buildGoogleMap(context),
_zoomMinusFunction(),
_zoomPlusFunction(),
],
),
);
}
Widget _zoomMinusFunction() {
return Align(
alignment: Alignment.topLeft,
child: IconButton(
icon: Icon(FontAwesomeIcons.searchMinus, color: Color(0xff6200ee)),
onPressed: () {
zoomValue--;
_minus(zoomValue);
}),
);
}
Widget _zoomPlusFunction() {
return Align(
alignment: Alignment.topRight,
child: IconButton(
icon: Icon(FontAwesomeIcons.searchPlus, color: Color(0xff6200ee)),
onPressed: () {
zoomValue++;
_plus(zoomValue);
}),
);
}
Future<void> _minus(double zoomValue) async {
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(target: LatLng(x, y), zoom: zoomValue)));
}
Future<void> _plus(double zoomValue) async {
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(target: LatLng(x, y), zoom: zoomValue)));
}
Widget _buildGoogleMap(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: GoogleMap(
mapType: MapType.normal,
initialCameraPosition:
CameraPosition(target: LatLng(x, y), zoom: 9),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
markers: {
aaa,
bbb,
},
),
);
}
#override
bool get wantKeepAlive => true;
}
Marker aaa = Marker(
markerId: MarkerId('aaa'),
position: LatLng(x, y),
infoWindow: InfoWindow(title: 'aaa', snippet: 'aaa'),
icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueViolet,
),
);
Marker bbb = Marker(
markerId: MarkerId('bbb'),
position: LatLng(x, y),
infoWindow:
InfoWindow(title: 'bbb', snippet: 'bbb'),
icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueViolet,
),
);
Sorry, I'm new to Flutter.
I know this is a little late, but if it still helps, this is what I have done.
_userLocation == null // If user location has not been found
? Center(
// Display Progress Indicator
child: CircularProgressIndicator(
backgroundColor: UniColors.primaryColour[500],
),
)
: GoogleMap(
// Show Campus Map
onMapCreated: _onMapCreated,
initialCameraPosition: // required parameter that sets the starting camera position. Camera position describes which part of the world you want the map to point at.
CameraPosition(
target: _userLocation,
zoom: defaultZoom,
tilt: 0.0),
scrollGesturesEnabled: true,
tiltGesturesEnabled: true,
trafficEnabled: false,
indoorViewEnabled: true,
compassEnabled: true,
rotateGesturesEnabled: true,
myLocationEnabled: true,
mapType: _currentMapType,
zoomGesturesEnabled: true,
cameraTargetBounds: new CameraTargetBounds(
new LatLngBounds(
northeast: uniCampusNE,
southwest: uniCampusSW,
),
),
minMaxZoomPreference:
new MinMaxZoomPreference(minZoom, maxZoom),
),
Related
want to find a center of 2 points and fit a map.
I want to fit for all screen when I view on map.
I draw route ready but it fit to 1 point only. please help me.
this class is for map view for a flutter.
I try to find plugin and solution more day but still not found.
GoogleMap(
mapType: MapType.normal,
markers: _markers,
// cameraTargetBounds: CameraTargetBounds(new LatLngBounds(
// northeast: LatLng(latFrom, logFrom),
// southwest: LatLng(latTo, logTo),
// )),
// minMaxZoomPreference: MinMaxZoomPreference(1, 15),
mapToolbarEnabled: true,
scrollGesturesEnabled: true,
zoomGesturesEnabled: true,
trafficEnabled: true,
compassEnabled: true,
indoorViewEnabled: true,
rotateGesturesEnabled: true,
tiltGesturesEnabled: true,
myLocationButtonEnabled: true,
myLocationEnabled: true,
polylines: _polyline,
// padding: EdgeInsets.all(20),
initialCameraPosition:
CameraPosition(
target: LatLng(latFrom, logFrom),
zoom: 10,
),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
})
void _setMapFitToTour(Set<Polyline> p) {
double minLat = p.first.points.first.latitude;
double minLong = p.first.points.first.longitude;
double maxLat = p.first.points.first.latitude;
double maxLong = p.first.points.first.longitude;
p.forEach((poly) {
poly.points.forEach((point) {
if(point.latitude < minLat) minLat = point.latitude;
if(point.latitude > maxLat) maxLat = point.latitude;
if(point.longitude < minLong) minLong = point.longitude;
if(point.longitude > maxLong) maxLong = point.longitude;
});
});
mapController.moveCamera(CameraUpdate.newLatLngBounds(LatLngBounds(
southwest: LatLng(minLat, minLong),
northeast: LatLng(maxLat,maxLong)
), 20));
}
google_maps_flutter: ^0.5.30
flutter_polyline_points: ^0.2.2
Make sure you have used .then() function because setPolyline() is the async function and has the await keyword.
Use these dependencies
class ShowMap extends StatefulWidget {
ShowMap({Key key}) : super(key: key);
#override
_ShowMapState createState() => _ShowMapState();
}
class _ShowMapState extends State<ShowMap> {
GoogleMapController _googleMapController;
Set<Polyline> _polylines = {};
List<LatLng> polylineCoordinates = [];
PolylinePoints polylinePoints = PolylinePoints();
String googleAPIKey = "YOUR_API_KEY_HERE";
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: ColorUtils.bluePrimary,
appBar: AppBar(
// automaticallyImplyLeading: false,
backgroundColor: ColorUtils.greenPrimary,
title: Center(
child: Column(
children: [
Text(
'Delivery Accepted! ',
style: TextStyle(fontSize: 18.0, letterSpacing: -0.3333),
),
],
),
),
),
body: Column(
children: [
Expanded(
flex: 5,
child: Center(
child: Container(
margin: EdgeInsets.only(top: 10),
decoration: BoxDecoration(
// color: Colors.white,
),
width: MediaQuery.of(context).size.width - 10,
height: MediaQuery.of(context).size.height * 0.5,
child: GoogleMap(
cameraTargetBounds: CameraTargetBounds.unbounded,
initialCameraPosition: _initialPosition,
onMapCreated: _onMapCreated,
tiltGesturesEnabled: true,
scrollGesturesEnabled: true,
zoomGesturesEnabled: true,
// trafficEnabled: true,
polylines: _polylines),
),
),
),
),
],
),
);
}
static final CameraPosition _initialPosition = CameraPosition(
// bearing: 192.8334901395799,
target: LatLng(31.5204, 74.3587),
zoom: 12);
void _onMapCreated(GoogleMapController controller) async {
setState(() {
_googleMapController = controller;
setPolylines().then((_) => _setMapFitToTour(_polylines));
});
}
void _setMapFitToTour(Set<Polyline> p) {
double minLat = p.first.points.first.latitude;
double minLong = p.first.points.first.longitude;
double maxLat = p.first.points.first.latitude;
double maxLong = p.first.points.first.longitude;
p.forEach((poly) {
poly.points.forEach((point) {
if (point.latitude < minLat) minLat = point.latitude;
if (point.latitude > maxLat) maxLat = point.latitude;
if (point.longitude < minLong) minLong = point.longitude;
if (point.longitude > maxLong) maxLong = point.longitude;
});
});
_googleMapController.animateCamera(CameraUpdate.newLatLngBounds(
LatLngBounds(
southwest: LatLng(minLat, minLong),
northeast: LatLng(maxLat, maxLong)),
20));
}
setPolylines() async {
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
googleAPIKey,
PointLatLng(31.5204, 74.3587),
PointLatLng(31.4504, 74.1350),
);
if (result.points.isNotEmpty) {
result.points.forEach((PointLatLng point) {
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
} else {
print("--address not found ---");
}
setState(() {
Polyline polyline = Polyline(
polylineId: PolylineId("poly"),
color: Color.fromARGB(255, 40, 122, 198),
width: 5,
points: polylineCoordinates);
_polylines.add(polyline);
});
}
}
Today I got the same problem and I stumbled upon your question. Looking through the answers while implementing i found a simpler approach.
The LatLangBounds class has a method in there called .fromPoint(List<LatLng> points) which takes a list of points and returns the bounds.
I used this with the MapController class and it worked perfectly showing the bounds on the map. Per my understanding of GoogleMapController it should work.
mapController.fitBounds(LatLngBounds.fromPoints(list_of_points));
Ideally this should be what the google map equivalent should be
googleMapController.moveCamera(
CameraUpdate.newLatLngBounds(
LatLngBounds.fromPoints(list_of_points)
),zoomIndex)
);
The .fromPoints(List<LatLng> points) method does what everyone has virtually implemented. Hopefully this helps anyone who needs it.
Today I got the same problem and I stumbled upon your question. And I found two links that can help.
https://medium.com/flutter-community/drawing-route-lines-on-google-maps-between-two-locations-in-flutter-4d351733ccbe
https://stackoverflow.com/a/55990256/1537413
after combine these two links, I get perfect solution.
Here you go.
import 'dart:async';
import 'package:app/env.dart';
import 'package:flutter/material.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class RoutePage extends StatefulWidget {
#override
_RoutePageState createState() => _RoutePageState();
}
class _RoutePageState extends State<RoutePage> {
Completer<GoogleMapController> _controller = Completer();
GoogleMapController mapController;
final Set<Marker> _markers = {};
Set<Polyline> _polylines = {};
List<LatLng> polylineCoordinates = [];
PolylinePoints polylinePoints = PolylinePoints();
String googleAPIKey = GOOGLE_MAPS_API_KEY;
static LatLng sourceLocation = LatLng(42.7477863, -71.1699932);
static LatLng destLocation = LatLng(42.6871386, -71.2143403);
void _onMapCreated(GoogleMapController controller) async {
mapController = controller;
_controller.complete(controller);
LatLng temp;
if (sourceLocation.latitude > destLocation.latitude) {
temp = sourceLocation;
sourceLocation = destLocation;
destLocation = temp;
}
LatLngBounds bound =
LatLngBounds(southwest: sourceLocation, northeast: destLocation);
BitmapDescriptor sourceIcon = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(devicePixelRatio: 2.5), 'assets/driving_pin.png');
BitmapDescriptor destinationIcon = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(devicePixelRatio: 2.5),
'assets/destination_map_marker.png');
setState(() {
_markers.clear();
addMarker(sourceLocation, "Madrid", "5 Star Rating", icon: sourceIcon);
addMarker(destLocation, "Barcelona", "7 Star Rating",
icon: destinationIcon);
});
CameraUpdate u2 = CameraUpdate.newLatLngBounds(bound, 50);
this.mapController.animateCamera(u2).then((void v) {
check(u2, this.mapController);
});
}
void addMarker(LatLng mLatLng, String mTitle, String mDescription,
{BitmapDescriptor icon}) {
_markers.add(Marker(
markerId: MarkerId(
(mTitle + "_" + _markers.length.toString()).toString()), //must unique
position: mLatLng,
infoWindow: InfoWindow(
title: mTitle,
snippet: mDescription,
),
icon: icon,
));
}
void check(CameraUpdate u, GoogleMapController c) async {
c.animateCamera(u);
mapController.animateCamera(u);
LatLngBounds l1 = await c.getVisibleRegion();
LatLngBounds l2 = await c.getVisibleRegion();
print(l1.toString());
print(l2.toString());
if (l1.southwest.latitude == -90 || l2.southwest.latitude == -90)
check(u, c);
else {
await setPolylines();
}
}
void _onCameraMove(CameraPosition position) {}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Maps Sample App'),
backgroundColor: Colors.green[700],
),
body: GoogleMap(
myLocationEnabled: true,
compassEnabled: true,
tiltGesturesEnabled: false,
markers: _markers,
polylines: _polylines,
mapType: MapType.normal,
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: sourceLocation,
zoom: 13.0,
),
onCameraMove: _onCameraMove,
),
),
);
}
setPolylines() async {
List<PointLatLng> result = await polylinePoints?.getRouteBetweenCoordinates(
googleAPIKey,
sourceLocation.latitude,
sourceLocation.longitude,
destLocation.latitude,
destLocation.longitude);
if (result.isNotEmpty) {
result.forEach((PointLatLng point) {
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
}
setState(() {
Polyline polyline = Polyline(
polylineId: PolylineId("poly"),
color: Color.fromARGB(255, 40, 122, 198),
points: polylineCoordinates);
_polylines.add(polyline);
});
}
}
I'm using Flutter's Geolocator and Google Maps packages to determine a device's location. I utilize the Circular Progress Bar to wait for the current location to be determined. Once determined, Google Maps loads with the device's location identified.
When the application loads, the circular progress bar is displayed but the map is not loaded despite the notification being displayed and accepted to use location services; the app hangs on the circular progress bar. I don't believe this to be an API issue as I have had success loading the map with coordinates specified in InitialCameraPosition.
Is the device's location not being determined which is the cause for the map to not load with the location indicated?
I've tried running the app on both Android emulator and a physical device without success.
Android Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="smartkart.app.com.coffee">
<!-- io.flutter.app.FlutterApplication is an android.app.Application
that
calls FlutterMain.startInitialization(this); in its onCreate
method.
In most cases you can leave this as-is, but you if you want to
provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:name="io.flutter.app.FlutterApplication"
android:label="coffee"
android:icon="#mipmap/ic_launcher">
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="API KEY HERE"/>
<activity../>
Maps Screen
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
class FirstScreen extends StatefulWidget {
const FirstScreen({Key key}) : super(key: key);
#override
State<FirstScreen> createState() => _FirstScreen();
}
class _FirstScreen extends State<FirstScreen> {
GoogleMapController mapController;
var currentLocation;
#override
void initState(){
super.initState();
Geolocator().getCurrentPosition().then((currloc){
currentLocation = currloc;
});
}
#override
Widget build(BuildContext context) {
return currentLocation == null ? Container(
alignment: Alignment.center,
child: Center(
child: CircularProgressIndicator(),
),
):
Stack(
children: <Widget>[
GoogleMap(
initialCameraPosition:
CameraPosition(target: LatLng(currentLocation.latitude,
currentLocation.longitude), zoom: 10),
onMapCreated: _onMapCreated,
myLocationEnabled: true,
mapType: MapType.normal,
),
],
);
}
void _onMapCreated(GoogleMapController controller) {
setState(() {
mapController = controller;
});
}
}
I expect the notification to use location services to appear while the circular progress bar is displayed. Once the location is determined, the InitialCameraPosition displays the device's location on the map.
Try the following code as a solution. You can modify the map widget to your use case:
import 'package:flutter/cupertino.dart';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class Map extends StatefulWidget {
#override
_MapState createState() => _MapState();
}
class _MapState extends State<Map> {
Completer<GoogleMapController> controller1;
//static LatLng _center = LatLng(-15.4630239974464, 28.363397732282127);
static LatLng _initialPosition;
final Set<Marker> _markers = {};
static LatLng _lastMapPosition = _initialPosition;
#override
void initState() {
super.initState();
_getUserLocation();
}
void _getUserLocation() async {
Position position = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
List<Placemark> placemark = await Geolocator().placemarkFromCoordinates(position.latitude, position.longitude);
setState(() {
_initialPosition = LatLng(position.latitude, position.longitude);
print('${placemark[0].name}');
});
}
_onMapCreated(GoogleMapController controller) {
setState(() {
controller1.complete(controller);
});
}
MapType _currentMapType = MapType.normal;
void _onMapTypeButtonPressed() {
setState(() {
_currentMapType = _currentMapType == MapType.normal
? MapType.satellite
: MapType.normal;
});
}
_onCameraMove(CameraPosition position) {
_lastMapPosition = position.target;
}
_onAddMarkerButtonPressed() {
setState(() {
_markers.add(
Marker(
markerId: MarkerId(_lastMapPosition.toString()),
position: _lastMapPosition,
infoWindow: InfoWindow(
title: "Pizza Parlour",
snippet: "This is a snippet",
onTap: (){
}
),
onTap: (){
},
icon: BitmapDescriptor.defaultMarker));
});
}
Widget mapButton(Function function, Icon icon, Color color) {
return RawMaterialButton(
onPressed: function,
child: icon,
shape: new CircleBorder(),
elevation: 2.0,
fillColor: color,
padding: const EdgeInsets.all(7.0),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _initialPosition == null ? Container(child: Center(child:Text('loading map..', style: TextStyle(fontFamily: 'Avenir-Medium', color: Colors.grey[400]),),),) : Container(
child: Stack(children: <Widget>[
GoogleMap(
markers: _markers,
mapType: _currentMapType,
initialCameraPosition: CameraPosition(
target: _initialPosition,
zoom: 14.4746,
),
onMapCreated: _onMapCreated,
zoomGesturesEnabled: true,
onCameraMove: _onCameraMove,
myLocationEnabled: true,
compassEnabled: true,
myLocationButtonEnabled: false,
),
Align(
alignment: Alignment.topRight,
child: Container(
margin: EdgeInsets.fromLTRB(0.0, 50.0, 0.0, 0.0),
child: Column(
children: <Widget>[
mapButton(_onAddMarkerButtonPressed,
Icon(
Icons.add_location
), Colors.blue),
mapButton(
_onMapTypeButtonPressed,
Icon(
IconData(0xf473,
fontFamily: CupertinoIcons.iconFont,
fontPackage: CupertinoIcons.iconFontPackage),
),
Colors.green),
],
)),
)
]),
),
);
}
}
You seem to be missing setState in your initState.
It should look like this:
#override
void initState(){
super.initState();
Geolocator().getCurrentPosition().then((currloc){
setState((){
currentLocation = currloc;
});
});
}
Use GeoLocator package with google_maps_flutter
Sample Code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
class MapScreen extends StatefulWidget {
#override
State<MapScreen> createState() => MapScreenState();
}
class MapScreenState extends State<MapScreen> {
LatLng initPosition = LatLng(0, 0); //initial Position cannot assign null values
LatLng currentLatLng= LatLng(0.0, 0.0); //initial currentPosition values cannot assign null values
LocationPermission permission = LocationPermission.denied; //initial permission status
Completer<GoogleMapController> _controller = Completer();
#override
void initState() {
super.initState();
getCurrentLocation();
checkPermission();
}
//checkPersion before initialize the map
void checkPermission() async{
permission = await Geolocator.checkPermission();
}
// get current location
void getCurrentLocation() async{
await Geolocator.getCurrentPosition().then((currLocation) {
setState(() {
currentLatLng =
new LatLng(currLocation.latitude, currLocation.longitude);
});
});
}
//call this onPress floating action button
void _currentLocation() async {
final GoogleMapController controller = await _controller.future;
getCurrentLocation();
controller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
bearing: 0,
target: currentLatLng,
zoom: 18.0,
),
));
}
//Check permission status and currentPosition before render the map
bool checkReady(LatLng? x, LocationPermission? y) {
if (x == initPosition || y == LocationPermission.denied || y == LocationPermission.deniedForever) {
return true;
} else {
return false;
}
}
#override
Widget build(BuildContext context) {
print(permission);
print("Current Location --------> " +
currentLatLng.latitude.toString() +
" " +
currentLatLng.longitude.toString());
return MaterialApp(
//remove debug banner on top right corner
debugShowCheckedModeBanner: false,
home: new Scaffold(
//ternary operator use for conditional rendering
body: checkReady(currentLatLng, permission)
? Center(child: CircularProgressIndicator())
//Stack : place floating action button on top of the map
: Stack(children: [
GoogleMap(
myLocationEnabled: true,
myLocationButtonEnabled: false,
zoomControlsEnabled: false,
mapType: MapType.normal,
initialCameraPosition: CameraPosition(target: currentLatLng),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
//Positioned : use to place button bottom right corner
Positioned(
bottom: 0,
right: 0,
child: Container(
margin: EdgeInsets.all(15),
child: FloatingActionButton(
onPressed: _currentLocation,
child: Icon(Icons.location_on)),
),
),
]),
),
);
}
}
I am trying to use google map api last version (0.5.7) but on my map there is only one marker that is printed but there are many markes on the database and it was working well before I tried to put the last version. Does someone know how to print many markers ? I put arrow where the markers are used.
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';
import 'package:geoflutterfire/geoflutterfire.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:rxdart/rxdart.dart';
import 'dart:async';
import 'package:intl/intl.dart';
import 'customs_icons_icons.dart';
import 'Dialogs.dart';
import 'Metro.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: FireMap(),
));
}
}
class FireMap extends StatefulWidget {
State createState() => FireMapState();
}
class FireMapState extends State<FireMap> {
GoogleMapController mapController;
Location location = new Location();
Dialogs dialogs = new Dialogs();
Firestore firestore = Firestore.instance;
Geoflutterfire geo = Geoflutterfire();
BehaviorSubject<double> radius = BehaviorSubject(seedValue: 100.0);
Stream<dynamic> query;
StreamSubscription subscription;`enter code here`
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
MarkerId selectedMarker;
int _markerIdCounter = 1;
build(context) {
return Stack(children: [
GoogleMap(
initialCameraPosition:
CameraPosition(target: LatLng(45.758077, 4.833316), zoom: 15),
onMapCreated: _onMapCreated,
myLocationEnabled: true,
mapType: MapType.normal,
compassEnabled: true,
markers: Set<Marker>.of(markers.values),<---
),
Positioned(
bottom: 20,
right: 20,
child: Container(
height: 80.0,
width: 80.0,
child: FittedBox(
child: FloatingActionButton(
child: Icon(CustomsIcons.ticket, color: Colors.black),
backgroundColor: Colors.pink[200],
onPressed: () => dialogs.information(
context, 'Confirmer ?', 'description', addGeoPoint),
),
),
),
),
]);
}
_onMapCreated(GoogleMapController controller) {
_startQuery();
setState(
() {
mapController = controller;
},
);
}
void _updateMarkers(List<DocumentSnapshot> documentList) { <---
final String markerIdVal = 'marker_id_$_markerIdCounter';
_markerIdCounter++;
final MarkerId markerId = MarkerId(markerIdVal);
print(documentList);
markers.clear();
documentList.forEach(
(DocumentSnapshot document) {
GeoPoint pos = document.data['position']['geopoint'];
var marker = Marker(
markerId: markerId,
position: LatLng(pos.latitude, pos.longitude),
icon: BitmapDescriptor.fromAsset('assets/ticket_point.png'),
infoWindow:
InfoWindow(title: 'Ici à :', snippet: document.data['time']));
setState(() {
markers[markerId] = marker;
});
},
);
}
It works ! I just moved markerIDcounter in "(DocumentSnapshot document)" and all the markers appears
I do it like this way
class _MapActivityState extends State<MapActivity> {
GoogleMapController _controller;
static LatLng _center = LatLng(0.0, 0.0);
Position currentLocation;
Set<Marker> _markers = {};
void _onMapCreated(GoogleMapController controller) {
setState(() {
_controller = controller;
});
}
#override
void initState() {
super.initState();
setState(() {
getUserLocation();
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text("Home"),
),
body: Stack(
children: <Widget>[
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(target: _center, zoom: 15),
markers: _markers,
),
],
),
);
}
getUserLocation() async {
currentLocation = await locateUser();
setState(() {
for (int i = 0; i < myresponse.data.length; i++) {
_markers.add(Marker(
markerId: MarkerId(myresponse[i].userId),
position: LatLng(double.parse(myresponse[i].latitude),
double.parse(myresponse[i].longitude)),
icon: myresponse[i].capacity.contains("7.2")
? BitmapDescriptor.fromAsset(
'assets/charger_location.png',
)
: BitmapDescriptor.fromAsset(
'assets/marker_green.png',
),
infoWindow: InfoWindow(
title: myresponse[i].stationName,
snippet: myresponse[i].contactPerson,
onTap: () => _onTap(myresponse[i]))));
}
});
}
}
The problem is how to infuse text overlap on the custom google map marker with text which represents the vehicle registration number.
I have tried to use this method to have the text overlay on the icon
builder: (context) =>()
But is not recognized at all.
class MapsDemo extends StatefulWidget {
#override
State createState() => MapsDemoState();
}
class MapsDemoState extends State<MapsDemo> {
GoogleMapController mapController;
//Map<PermissionGroup, PermissionStatus> permissions = await PermissionHandler().requestPermissions([PermissionGroup.contacts]);import 'package:permission_handler/permission_handler.dart';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: GoogleMap(
onMapCreated: (GoogleMapController controller) {
mapController = controller;
},
),
),
],
),
floatingActionButton: FloatingActionButton(onPressed: () {
double mq1 = MediaQuery.of(context).devicePixelRatio;
String icon = "images/car.png";
if (mq1>1.5 && mq1<2.5) {icon = "images/car2.png";}
else if(mq1 >= 2.5){icon = "images/car3.png";}
print("Mq 1"+mq1.toStringAsFixed(5));
String iconPath="lib/assets/move#3x.png";
mapController.addMarker(
MarkerOptions(
position: LatLng(37.4219999, -122.0862462),
infoWindowText: InfoWindowText("TEST","TEST"),
icon: BitmapDescriptor.fromAsset(iconPath),
consumeTapEvents: true,
/*builder: (context) =>(
)*/
//icon:BitmapDescriptor.fromAsset(assetName)
),
);
mapController.addMarker(
MarkerOptions(
position: LatLng(38.4219999, -122.0862462),
infoWindowText: InfoWindowText("tt","adfaf"),
icon: BitmapDescriptor.fromAsset("lib/assets/logo.png"),
anchor: Offset(100,160),
//icon:BitmapDescriptor.fromAsset(assetName)
),
);
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(37.4219999, -122.0862462),
zoom: 15.0,
),
),
);
})
);
}
}
What I have shown is the icon appear correctly if you notice the white space on the right of the icon is where I want the registration number to appear.
try this :
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MapsDemo extends StatefulWidget {
#override
State createState() => MapsDemoState();
}
class MapsDemoState extends State<MapsDemo> {
final Set<Marker> _markers = {};
void _onAddMarkerButtonPressed() {
print('in _onAddMarkerButtonPressed()');
setState(() {
_markers.add(Marker(
// This marker id can be anything that uniquely identifies each marker.
markerId: MarkerId("111"),
position: LatLng(30.666, 76.8127),
infoWindow: InfoWindow(
title: "bingo! This works",
),
icon: BitmapDescriptor.defaultMarker,
));
});
print('setState() done');
}
GoogleMapController mapController;
//Map<PermissionGroup, PermissionStatus> permissions = await PermissionHandler().requestPermissions([PermissionGroup.contacts]);import 'package:permission_handler/permission_handler.dart';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: GoogleMap(
markers: _markers,
onMapCreated: (GoogleMapController controller) {
mapController = controller;
},
initialCameraPosition:
CameraPosition(target: LatLng(30.666, 76.8127), zoom: 15),
),
),
],
),
floatingActionButton: FloatingActionButton(onPressed: () {
print('in fab()');
double mq1 = MediaQuery.of(context).devicePixelRatio;
_onAddMarkerButtonPressed();
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(30.666, 76.8127),
zoom: 15.0,
),
),
);
}));
}
}
I kludged/solved this by creating a function which returned a , whose returned and resolved value I then passed in as the icon when initializing a Marker:
Sorry to say that I don't remember why I padded the method with the magic 40 and 20 constants. Probably calculated by visual test with what I was rendering at the time.
Future<BitmapDescriptor> createCustomMarkerBitmap(/* your args here */) async {
PictureRecorder recorder = new PictureRecorder();
Canvas c = new Canvas(recorder);
/* Do your painting of the custom icon here, including drawing text, shapes, etc. */
Picture p = recorder.endRecording();
ByteData pngBytes = await (await p.toImage(
tp.width.toInt() + 40, tp.height.toInt() + 20))
.toByteData(format: ImageByteFormat.png);
Uint8List data = Uint8List.view(pngBytes.buffer);
return BitmapDescriptor.fromBytes(data);
}
Then when creating the marker, you can pass in the BitmapDescriptor as the icon, like so:
createCustomMarkerBitmap(...).then((BitmapDescriptor bitmapDescriptor) {
_markers.add(new Marker(
/* in addition to your other properties: */
icon: bitmapDescriptor,
));
});
or:
BitmapDescriptor bitmapDescriptor = await createCustomMarkerBitmap(...);
Marker marker = Marker(
/* in addition to your other properties: */
icon: bitmapDescriptor
);
Let me know if that helps. Gl!
I have found this answer for github issue
I found myself on this exact stackoverflow page multiple times this year. So, I decided to go and make my first Flutter Package and created this. If your objective is to add a simple and clear text to map marker, this would do it.
https://pub.dev/packages/label_marker
Usage
markers.addLabelMarker(LabelMarker(
label: "TextToShow",
markerId: MarkerId("idString"),
position: LatLng(10.0, 11.0),
backgroundColor: Colors.green,
)).then((value) {
setState(() {});
},
);
In my flutter app. I am using google_maps_plugin . The link is https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter .
I want to fix the marker in center of map without movable after draging the map.
I want it likes http://jsfiddle.net/UuDA6/
In my code i am using MarkerOption for placing the marker.
MarkerOptions options = new MarkerOptions(
alpha: 1.0,
anchor: Offset(0.5, 1.0),
consumeTapEvents: false,
draggable: false,
flat: false,
icon: BitmapDescriptor.defaultMarker,
infoWindowAnchor: Offset(0.5, 0.0),
infoWindowText: InfoWindowText.noText,
position: LatLng(17.411439, 78.5486697),
rotation: 0.0,
visible: true,
zIndex: 0.0,
);
But in the position i want to know how to give the center of map.
If any one have idea about it please share it.
Actually with new update of google_maps_flutter: ^0.4.0 we can achieve above requirement easily.
This is the demo link.
Map<MarkerId, Marker> _markers = <MarkerId, Marker>{};
int _markerIdCounter = 0;
Completer<GoogleMapController> _mapController = Completer();
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: GoogleMap(
markers: Set<Marker>.of(_markers.values),
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: Constants.LOCATION_SRI_LANKA,
zoom: 12.0,
),
myLocationEnabled: true,
onCameraMove: (CameraPosition position) {
if(_markers.length > 0) {
MarkerId markerId = MarkerId(_markerIdVal());
Marker marker = _markers[markerId];
Marker updatedMarker = marker.copyWith(
positionParam: position.target,
);
setState(() {
_markers[markerId] = updatedMarker;
});
}
},
),
)
void _onMapCreated(GoogleMapController controller) async {
_mapController.complete(controller);
if ([INITIAL_LOCATION] != null) {
MarkerId markerId = MarkerId(_markerIdVal());
LatLng position = [INITIAL_LOCATION];
Marker marker = Marker(
markerId: markerId,
position: position,
draggable: false,
);
setState(() {
_markers[markerId] = marker;
});
Future.delayed(Duration(seconds: 1), () async {
GoogleMapController controller = await _mapController.future;
controller.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: position,
zoom: 17.0,
),
),
);
});
}
}
String _markerIdVal({bool increment = false}) {
String val = 'marker_id_$_markerIdCounter';
if (increment) _markerIdCounter++;
return val;
}
This is based on the #Joe answer but it has more accurated pin position and no other class is required:
double mapWidth = MediaQuery.of(context).size.width;
double mapHeight = MediaQuery.of(context).size.height - 215;
double iconSize = 40.0;
return new Stack(
alignment: Alignment(0.0, 0.0),
children: <Widget>[
new Container(
width: mapWidth,
height: mapHeight,
child: _googleMap
),
new Positioned(
top: (mapHeight - iconSize)/ 2,
right: (mapWidth - iconSize)/ 2,
child: new Icon(Icons.person_pin_circle, size: iconSize),
)
]);
This solution don't require to repaint the entire Screen (no setState call) when user update the position. You won't see that weird marker "movement".
The right answer is to use Stack and overlay marker pin on map. if you try to put marker on map using GoogleMaps markers property, you have to update marker position on CameraMove and call setState which add latency on redrawing maker.
compare two approaches:
class StoreLocationMap extends StatefulWidget {
final Coordinate userLocation;
const StoreLocationMap({Key? key, required this.userLocation})
: super(key: key);
#override
_StoreLocationMapState createState() => _StoreLocationMapState();
}
class _StoreLocationMapState extends State<StoreLocationMap> {
final List<Marker> _markers = [];
#override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: [
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(
widget.userLocation.latitude, widget.userLocation.longitude),
zoom: 14),
markers: _markers.toSet(),
onMapCreated: (controller) {
final marker = Marker(
markerId: MarkerId('0'),
position: LatLng(
widget.userLocation.latitude, widget.userLocation.longitude),
);
_markers.add(marker);
},
onCameraMove: (position) {
setState(() {
_markers.first =
_markers.first.copyWith(positionParam: position.target);
});
},
),
Image.asset(
'assets/images/delivery-area-start-pin.png',
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
return Transform.translate(
offset: const Offset(8, -37),
child: child,
);
},
)
],
);
}
}
As my custom marker has shadow and is not symmetric, I used Transform widget to translate custom marker to point to right location.
How to get map center coordinate? or center maker position?
User onCameraMove to get map center position:
onCameraMove: (position) {
print(position.target);
},
It is possible using stack. The code is shown below.
Stack(
children: <Widget>[
GoogleMap(
onMapCreated: _onMapCreated,
),
InfoView()
],)
The InfoView is
class InfoView extends State<AppPage> {
const InfoView({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return new Align(
alignment: Alignment.center,
child: new Icon(Icons.person_pin_circle, size: 40.0),
);
}
}
Then the _onMapCreated is
void _onMapCreated(GoogleMapController controller) {
setState(() {
mapController = controller;
mapController.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
bearing: 270.0,
target: LatLng(lattitude, longitude),
tilt: 30.0,
zoom: 17.0,
),
));
});
}
}
This stack class is useful if you want to overlap several children in a simple way, for example having some text and an image, overlaid with a gradient and a button attached to the bottom.
I recommend to you to try this new Flutter package https://pub.dev/packages/flutter_animarker
Use Stack and IgnorePointer to ignore touches on your widget
Stack(
children: <Widget>[
GoogleMap(
....
),
Center(
child: IgnorePointer(
child: ...
)
)
]
)