I display in my application a google map and a marker on a predefined position. I also changed the icon of the marker but it is too large and above all does not adapt to the size of the screen and its definition.
I would therefore like to adapt the dimensions of cd nouveau marker to the size of my screen. First of all, how to change its size?
My code is the following:
class _MyAppState extends State<MyApp>{
late GoogleMapController mapController;
....
late BitmapDescriptor iconMareaEstLa;
final List<Marker> _listMk =[];
....
void _onMapCreated(GoogleMapController controller){
mapController = controller;
setState(() {
_listMk.add(
Marker(
markerId: const MarkerId('MKIDPOSMAREA'),
draggable: false,
icon: iconMareaEstLa,
position: (LatLng(posMareaLat,posMareaLng)),
)
);
});
}
....
#override
void initState(){
super.initState();
BitmapDescriptor
.fromAssetImage(
const ImageConfiguration(size:Size(50,50)),
'images/MareaBlancFondBlanc.png')
.then((value) => iconMareaEstLa = value);
}
...
Widget build(BuildContext context) {
MediaQueryData queryData;
queryData = MediaQuery.of(context);
screenW =queryData.size.width;
screenH =queryData.size.height;
return Scaffold(
body: Stack(
children: [
GoogleMap(
markers: Set.of(_listMk),
onMapCreated: _onMapCreated,
mapType: _currentMapType,
myLocationButtonEnabled: false,
zoomControlsEnabled: false,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 14.0
),
),
....
Can someone tell me where and how to specify the dimensions of my new marker.
Merci
YC
Related
Here's the code that I have so far
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class TempView extends StatefulWidget {
const TempView({Key? key}) : super(key: key);
#override
State<TempView> createState() => _TempViewState();
}
class _TempViewState extends State<TempView> {
final Completer<GoogleMapController> _controller =
Completer<GoogleMapController>();
static const CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(37.42796133580664, -122.085749655962),
zoom: 14.4746,
);
static const CameraPosition _kLake = CameraPosition(
bearing: 192.8334901395799,
target: LatLng(37.43296265331129, -122.08832357078792),
tilt: 59.440717697143555,
zoom: 19.151926040649414);
#override
Widget build(BuildContext context) {
return Scaffold(
body: GoogleMap(
onTap: (argument) => print("tapped"),
mapType: MapType.hybrid,
initialCameraPosition: _kGooglePlex,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
floatingActionButton: FloatingActionButton.extended(
onPressed: _goToTheLake,
label: const Text('To the lake!'),
icon: const Icon(Icons.directions_boat),
),
);
}
Future<void> _goToTheLake() async {
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(_kLake));
}
}
It's the same as the code on the pub.dev page for the google_maps_flutter widget, except I added an onTap.
For some reason the onTap never fires! I've even tried adding custom gesture recognisers into the gestureRecognizers set, like the EagerGestureRecognizer and the TapGestureRecognizer.
I'm on Flutter 3.7 macOS with Apple M1.
Why isn't it working, and how can I get around this?
Wrap GoogleMap widget with InkWell Widget and use its property of onTap, it will work.
InkWell(
onTap: () => ,
child:
),
I ran your code and it seems to run just fine. tapped gets printed every time i tap on map.
Please make sure your tap is in GoogleMap region and that no other widget is overlaying if this isn’t the whole code.
I ran into a bit of a wall when i tried to implement marker clustering in a Google Maps based app that i'm developing for work.
I figured i could use circles to represent clusters and swap markers for circles at a certain zoom threshold but that didn't work out, so now I'm using a clustering library.
The main issue is that said library doesn't take into account if the app uses a state management library, so here i am with an empty map once again.
I render my map like this:
class MapView extends StatelessWidget {
final LatLng initialLocation;
final Set<Marker> markers;
final CustomInfoWindowController infoWindowController;
final GoogleMapController? mapController;
final ClusterManager manager;
Completer<GoogleMapController> newMapController = Completer();
MapView(
{Key? key,
required this.initialLocation,
required this.markers,
required this.manager,
required this.infoWindowController,
this.mapController})
: super(key: key);
#override
Widget build(BuildContext context) {
final CameraPosition initialCameraPosition =
CameraPosition(target: initialLocation);
final renderSize = MediaQuery.of(context).size;
return SizedBox(
width: renderSize.width,
height: renderSize.height,
child: GoogleMap(
onTap: (position) {
infoWindowController.hideInfoWindow!();
if (context.read<MapBloc>().state.creatingLocation == true) {
context.read<MapBloc>().add(TurnCreationModeOff());
}
},
onCameraMove: (position) {
infoWindowController.onCameraMove!();
manager.onCameraMove(position);
},
onCameraIdle: () {
context.read<MapBloc>().add(HoldZoomLevel());
manager.updateMap();
context.read<MapBloc>().printMapID();
},
onLongPress: (LatLng location) {
context
.read<LocationCreationBloc>()
.add(LocationAcquired(location: location));
final Marker newMarker = Marker(
draggable: true,
markerId: const MarkerId('new'),
position: location,
icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueViolet),
infoWindow: InfoWindow(
title: 'Pulsame para crear una nueva ubicacion',
snippet:
'Toca cualquier lado del mapa y reajusta el zoom para destruirme',
onTap: () {
Navigator.of(context).pushAndRemoveUntil(
CreationScreen.route(), (route) => false);
},
));
context.read<MapBloc>().add(RenderNewMarker(marker: newMarker));
},
initialCameraPosition: initialCameraPosition,
compassEnabled: true,
myLocationEnabled: true,
markers: markers,
zoomControlsEnabled: false,
myLocationButtonEnabled: true,
mapToolbarEnabled: false,
onMapCreated: (GoogleMapController controller) {
context.read<MapBloc>().add(MapInitialized(
controller: controller,
windowController: infoWindowController,
clusterManager: manager,
location:
context.read<LocationBloc>().state.lastKnownLocation));
newMapController.complete(controller);
manager.setMapId(controller.mapId);
infoWindowController.googleMapController = controller;
},
)
);
}
}
some stuff is heavily context dependant and i'd be happy to elaborate and provide more code samples if anyone needs them or has run into a similar issue.
i tried recoupling my business logic with my presentation layer, that being initializing a List of clusterable items and passing it to the Cluster Manager constructor but it crashed at runtime.
I am new to Flutter and I have created a google map using the flutter_google_maps package.
I have the following code in my parent widget,
SizedBox(
child: _showFindHouseModal
? FutureBuilder<Address?>(
future: _locationDataFuture,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Map(
initialLatitude: _userLocation.latitude!.toDouble(),
initialLongitude: _userLocation.longitude!.toDouble(),
markers: const [],
);
}
},
)
: FutureBuilder<Address?>(
future: _showFindHouseModal,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Map( // <---------------------------------------- This one is the problem
initialLongitude: _userLocation.latitude!.toDouble(),
initialLatitude: _userLocation.latitude!.toDouble(),
markers: [
Marker(
markerId: MarkerId('${_housesList.first.id}'),
position: LatLng(_housesList.first.houseLatitude, _housesList.first.houseLongitude),
),
],
);
}
}),
),
In the above code, you can see that I am using a ternary operator. if _showFindHouseModal is true a Map widget is built. If it is not true, the same Map widget will be built but with additional markers. The problem is, those additional markers I am forwarding are not rendered on the screen.
However, I think I figured out the problem. It is in the child widget. (It is that I can not find a solution to the problem)
Let me show the code for the child widget.
class Map extends StatefulWidget {
final List<Marker> markers;
final double initialLatitude;
final double initialLongitude;
const Map({
Key? key,
required this.initialLatitude,
required this.initialLongitude,
required this.markers, // Todo: Make the default to an empty value
}) : super(key: key);
#override
State<Map> createState() => MapState();
}
class MapState extends State<Map> {
late final CameraPosition _initialCameraPosition;
late final Set<Marker> _markers = {};
final Completer<GoogleMapController> _controller = Completer();
#override
void initState() {
super.initState();
_initialCameraPosition = CameraPosition(
target: LatLng(widget.initialLatitude, widget.initialLongitude),
zoom: 12,
);
}
#override
Widget build(BuildContext context) {
return GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _initialCameraPosition,
markers: _markers,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
setState(
() {
_markers.addAll(widget.markers); <--------- This is the problem I think
_markers.add(
Marker(
markerId: const MarkerId('user-marker'),
position: LatLng(widget.initialLatitude, widget.initialLongitude),
),
);
},
);
},
);
}
}
As I have pointed out in the code, I think the problem is, inside the child widget, those markers are added under the onMapCreated property. Since the map is already created in the first FutureBuilder, those markers are not added to the map for some reason. I can not figure out how to add new markers from the second FutureBuilder. The markers I am adding are not passed through.
Can someone please help. I have been trying to find a way for 6 or so hours and could not make it.
try this, change the line you assign the markers
markers: _markers
along this line
markers: Set<Marker>.of(_markers.values),
this may help you
bool mapToggle = false;
Position currentLocation;
GoogleMapController mapController;
GoogleMap googleMap;
var ads = [];
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
MarkerId selectedMarker;
LatLng markerPosition;
bool clientToggle = false;
#override
void initState() {
super.initState();
// GeolocationStatus geolocationStatus = await Geolocator.checkGeolocationPermissionStatus();
// Geolocator.checkPermission();
// Geolocator.getServiceStatusStream();
Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high)
.then((currloc) {
setState(() {
currentLocation = currloc;
mapToggle = true;
populateClient();
});
});
}
#override
void dispose() {
super.dispose();
}
populateClient() {
kfirestore.collection('marks').get().then((value) {
if (value.docs.isNotEmpty) {
setState(() {
clientToggle = true;
});
for (int i = 0; i < value.docs.length; i++) {
ads.add(value.docs[i].data());
initMarker(value.docs[i].data(), value.docs[i].id);
var _distanceBetweenLastTwoLocations = Geolocator.distanceBetween(
value.docs[i].data()['location'].latitude,
value.docs[i].data()['location'].longitude,
currentLocation.latitude,
currentLocation.longitude,
);
print("bairshiluud:" + _distanceBetweenLastTwoLocations.toString());
if (_distanceBetweenLastTwoLocations < 100) {
SuccessDialog(
title: "Таны байршилтай ойр сурталчилгаа",
titleColor: Colors.green,
description: value.docs[i].data()['adName'],
);
} else {
SuccessDialog(
title: "Таны байршилтай ойр сурталчилгаа",
titleColor: Colors.green,
description: "Таны байршилд ойр сурталчилгаа олдсонгүй.",
);
}
}
}
});
}
void initMarker(specify, specifyId) async {
var markerIdVal = specifyId;
final MarkerId markerId = MarkerId(markerIdVal);
final Marker marker = Marker(
markerId: markerId,
position: LatLng(
specify['location'].latitude,
specify['location'].longitude,
),
infoWindow: InfoWindow(title: specify['adName'], snippet: "Сурталчилгаа"),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRose),
);
setState(() {
markers[markerId] = marker;
});
}
Container(
height: MediaQuery.of(context).size.height - 80,
width: double.infinity,
child: mapToggle
? GoogleMap(
mapType: MapType.hybrid,
compassEnabled: true,
onMapCreated: onMapCreated,
buildingsEnabled: true,
myLocationButtonEnabled: true,
myLocationEnabled: true,
rotateGesturesEnabled: true,
zoomControlsEnabled: true,
zoomGesturesEnabled: true,
indoorViewEnabled: true,
mapToolbarEnabled: true,
tiltGesturesEnabled: true,
scrollGesturesEnabled: true,
initialCameraPosition: CameraPosition(
target: LatLng(currentLocation.latitude,
currentLocation.longitude),
zoom: 15,
),
// circles: circles,
markers: Set<Marker>.of(markers.values),
)
: Center(
child: Text("Loading"),
),
),
1- It is not high possibile but maybe you can change markers: const [] line to just [] without cons keyword.
2- This one more possible than first one, try to cover with one of them future builder, with different widget like SizedBox or give one of them unique key. (but i suggest first approach like; condition? FutureBuilder:SizedBox(child: FutureBuilder)) because, your problem can be releated widget tree rendering. İf this solve your problem I can add a youtube link about that and you can understand the meaning what I am trying to point out.
3- for camera position, after on camera create function call, with help initialed googleMapsController, you can change camera position, camera zoom and some other stuffs with googleMapsController.animateCamera() function,
example; googleMapsController.animateCamera(CameraUpdate.newLatLng(latLng)) will change the google maps view to your new lat long point. So I suggest, dont't use future builder for this, just animate your camera after initialing and you can cover your map widget with IgnorePointer before getting locations, in this way you can ensure the animation can't block from user interaction.
I am trying to get the user's current location from Google Maps but I am getting an exception in return which I can't seem to understand why it's happening.
The app is simple - get the user's current location, and then zoom the camera onto that location. That's it.
I am going to attach my code and the exception message. The strange thing is that I am getting my LatLng correctly as you can see in the exception message, so why is the camera not pointing to that location?
class Map extends StatefulWidget {
#override
_MapState createState() => _MapState();
}
class _MapState extends State<Map> {
LatLng currentLatLng;
Completer<GoogleMapController> _controller = Completer();
#override
void initState(){
super.initState();
Geolocator.getCurrentPosition().then((currLocation){
setState((){
currentLatLng = new LatLng(currLocation.latitude, currLocation.longitude);
});
});
}
#override
Widget build(BuildContext context) {
print("Current Location --------> " + currentLatLng.latitude.toString() + " " + currentLatLng.longitude.toString());
return MaterialApp(
home: new Scaffold(
body: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: CameraPosition(target: currentLatLng),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
),
);
}
}
note - I am using 'geolocator' and 'google_maps_flutter' from pub.dev - all latest versions.
This is async programming. currentLatLng is null until getCurrentPosition calls it's callback, so you can't just do this:
initialCameraPosition: CameraPosition(target: currentLatLng)
because, as you error shows, currentLatLng is null.
Your two options are:
Set the map to a default position that you define and then update the position using the mapcontroller when getCurrentPosition completes.
Show a loader while currentLatLng is null, and when it's no longer null, show your map.
Here's an example for 2
return MaterialApp(
home: new Scaffold(
body: currentLatLng == null ? Center(child:CircularProgressIndicator()) : GoogleMap(
mapType: MapType.normal,
initialCameraPosition: CameraPosition(target: currentLatLng),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
),
);
I'm using google_maps_flutter package to display the map and I placed a marker so the user can select a location (not the user location any location on the map).
like this
Now the user can drag the marker where he want ,
my question is
Can I get latitude and longitude for marker after user drag it?
here is my full code
class _BodyState extends State<Body> {
MapType mapType = MapType.normal;
Completer<GoogleMapController> _controller = Completer();
LocationServices _locationServices;
LocationData _locationData;
CameraPosition _cameraPosition;
Set<Marker> allMapMarkers;
Marker userPicker;
#override
Widget build(BuildContext context) {
_locationServices=Provider.of<LocationServices>(context);
return FutureBuilder(
future: _locationServices.getLocation().then((LocationData value) => _locationData=value),
builder:(context,snapshot){
if(_locationData==null){
return Center(child: CircularProgressIndicator());
}else{
_cameraPosition=CameraPosition(target:LatLng(_locationData.latitude,_locationData.longitude),zoom: 19);
setupMarkers(); // this set the Lat and Long for marker
return SafeArea(
child: Stack(
children: [
GoogleMap(
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
initialCameraPosition: _cameraPosition,
mapType: mapType,
compassEnabled: false,
zoomControlsEnabled: false,
markers: allMapMarkers,
),
You can use the Marker from google_maps_flutter plugin to fetch marker coordinates. It has an onDrag property that returns a LatLng object that contains coordinates. Use the onDragEnd property to fetch the coordinates on where the marker has been placed.
Marker(
onTap: () {
debugPrint('Tapped');
},
draggable: true,
markerId: MarkerId('Marker'),
onDragEnd: ((LatLng newPosition) {
debugPrint(newPosition.latitude);
debugPrint(newPosition.longitude);
}),
)