i want to get the current latlng which is centered on the screen. like uber tells name of the place while we are moving the map on the screen it updates the value.
You can use the property onCameraMove of GoogleMap class.
GoogleMap(
onCameraMove: (CameraPosition position) {
print("Latitude: ${position.target.latitude}; Longitude: ${position.target.longitude}");
},
[...]
)
More info about GoogleMap and onCameraMove.
onCameraMove you can get the center location of the screen
and then you can easily use setState to update the value
GoogleMap(
onCameraMove: (object) => {
setState(() {
latitude = object.target.latitude;
longitude = object.target.longitude;
})
},
Related
I have a SearchMapPlaceWidget that suggests me places based on my search keyword. I want to animate the camera to the suggested place I tap on. How do I do that?
Here's the SearchMapPlaceWidget that I used from search_map_place package in Flutter.
SearchMapPlaceWidget(
apiKey: myApiKey,
onSearch: (Place place) async {
try{
final geolocation = await place.geolocation;
print(geolocation);
}catch(e){
print(e);
}
},
),
From official example https://pub.dev/packages/search_map_place#example
You can use GoogleMapController and call animateCamera
return SearchMapPlaceWidget(
apiKey: YOUR_API_KEY,
// The language of the autocompletion
language: 'en',
// The position used to give better recomendations. In this case we are using the user position
location: userPosition.coordinates,
radius: 30000,
onSelected: (Place place) async {
final geolocation = await place.geolocation;
// Will animate the GoogleMap camera, taking us to the selected position with an appropriate zoom
final GoogleMapController controller = await _mapController.future;
controller.animateCamera(CameraUpdate.newLatLng(geolocation.coordinates));
controller.animateCamera(CameraUpdate.newLatLngBounds(geolocation.bounds, 0));
},
);
From Official example have all the code you need
Screen with map and search box on top. When the user selects a place through autocompletion,the screen is moved to the selected location
https://github.com/Bernardi23/search_map_place/blob/master/example/advanced_example.dart
You can directly run this example
It's too long, I just paste _mapController part
Completer<GoogleMapController> _mapController = Completer();
...
GoogleMap(
...
onMapCreated: (GoogleMapController controller) async {
_mapController.complete(controller);
...
final GoogleMapController controller = await _mapController.future;
I have a GoogleMap in my Flutter app.
When the page loads it calls on API and gets a list of geolocations which I use to create a list of markers.
My GoogleMap uses this list of markers and they display nicely, however, I would like one of them to be active. I can't see anything in the API documentation that says this is possible. How can I achieve this?
Use GoogleMapController to set the marker active, allMarkers here is a list of markers which might be coming from the database and the first one (index 0) will be active after execution of:
_googleMapController.showMarkerInfoWindow(allMarkers[0].markerId);
Documentation
You can implement custom active state through onTap event handler.
In stateful widget create state to track selected marker and rebuild all markers comparing their IDs to the highlighted one:
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class GoogleMapsLabPage extends StatefulWidget {
#override
State<GoogleMapsLabPage> createState() => GoogleMapsLabPageState();
}
class GoogleMapsLabPageState extends State<GoogleMapsLabPage> {
final preset = [
{"id": "mountain-view", "lat": 37.421512, "lng": -122.084101},
{"id": "san-bruno", "lat": 37.62816, "lng": -122.426491},
{"id": "san-francisco", "lat": 37.789972, "lng": -122.390013},
{"id": "sunnyvale", "lat": 37.403694, "lng": -122.031583}
];
String _selectedOffice = '';
List<Marker> _buildMarkers() {
return preset.map((office) {
return Marker(
markerId: MarkerId(office['id']),
position: LatLng(office['lat'], office['lng']),
icon: office['id'] == _selectedOffice
? BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue)
: BitmapDescriptor.defaultMarker,
consumeTapEvents: true,
onTap: () {
setState(() {
_selectedOffice = office['id'];
});
});
});
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: GoogleMap(
initialCameraPosition: CameraPosition(target: LatLng(37.7, -122.2), zoom: 9.0),
markers: _buildMarkers().toSet(),
),
);
}
}
By setting consumeTapEvents parameter to true we can disable default tap handling by centering the map on the marker and displaying its info window.
There are ongoing issues in flutter related to the same thing here and here.
Currently, It is not possible to do this via official maps SDK.
However, thanks to the community there is another forked project which has an implementation which can help you achieve this. Checkout this.
mapController.addMarker(
MarkerOptions(
position: LatLng(your values here),
),
);
I'm currently using GoogleMap in Flutter. I also use the clustering_google_maps package to display clusters of markers. The default behavior of this plugin is that every camera movement triggers an update of all the markers and clusters. This behavior takes into account the user zoom in/out and translation.
I added a feature where the camera moves according to the user's location whith the location package.
initPlatformState() async {
// Wait for the Completer to complete and return the GoogleMap Controler
mapController = await _controller.future;
// Set controller for the ClusteringHelper
clusteringHelper.mapController = mapController;
// Get database and update markers
clusteringHelper.database = await DBHelper().database;
clusteringHelper.updateMap();
// Set parameters for location Service
await _locationService.changeSettings(
accuracy: LocationAccuracy.HIGH, interval: 1000);
try {
bool serviceStatus = await _locationService.serviceEnabled();
print("Service status: $serviceStatus");
if (serviceStatus) {
_permission = await _locationService.requestPermission();
print("Permission: $_permission");
// If permission granted, get current location and subscribe to updates
if (_permission) {
LocationData location = await _locationService.getLocation();
final myLocationMarkerId = MarkerId("myLocationMarker");
myLocationMarker = Marker(
markerId: myLocationMarkerId,
position: LatLng(location.latitude, location.longitude),
icon: BitmapDescriptor.defaultMarker,
infoWindow: InfoWindow(
title: "My Location",
snippet: "Latitude: " +
location.latitude.toString() +
" Longitude: " +
location.longitude.toString()),
);
_locationSubscription = _locationService
.onLocationChanged()
.listen((LocationData result) async {
if (cameraUpdateToMyLocation) {
_currentCameraPosition = CameraPosition(
target: LatLng(result.latitude, result.longitude), zoom: 16);
// Safety check if mapController not null
if (mapController != null) {
mapController.animateCamera(
CameraUpdate.newCameraPosition(_currentCameraPosition));
}
}
if (mounted) {
setState(() {
_currentLocation = result;
myLocationMarker = myLocationMarker.copyWith(
positionParam: LatLng(
_currentLocation.latitude, _currentLocation.longitude),
infoWindowParam: InfoWindow(
title: "My Location",
snippet: "Latitude: " +
location.latitude.toString() +
" Longitude: " +
location.longitude.toString())
);
});
}
});
}
} else {
bool serviceStatusResult = await _locationService.requestService();
print("Service status activated after request: $serviceStatusResult");
if (serviceStatusResult) {
initPlatformState();
}
}
} on PlatformException catch (e) {
print(e);
if (e.code == 'PERMISSION_DENIED') {
error = e.message;
} else if (e.code == 'SERVICE_STATUS_ERROR') {
error = e.message;
}
}
}
I would like that this location update stops when the user moves the maps on the screen.
Unfortunately, the callback onCameraMove is triggered when the user move the map AND when the camera animation is launched.
Is it possible to trigger the inCameraMove callback, only when the user move the map ?
Thx !
EDIT It appears that onCameraMove is called in loop when I drag the map with my finger...
It's not possible to differentiate the onCameraMove callback as far as I know. What are you trying to accomplish here? Can you change the plugin to display the clusters onCameraIdle callback? Would this solve your problem?
unfortunately, the google maps flutter does not support this feature for now. you can handle it by wrapping a map in the listener and control a boolean that shows what kind of action makes the camera move. for example, I want to find out if the camera moves by click on the markers (calling on tap callback of marker moves the camera) or the user manually drags the map. every time the user touches the map I change the "dragsTheScreen" boolean to true, and in on tap function of markers I change it to false which shows the camera movement is because of markers. so you can do it for any feature you want. for example, you want to find out if the camera movement is because of calling your own Special function or the user dragging: listener changes the boolean("dragsTheScreen") to true, and that function setState it to false.
Listener(
onPointerDown: (PointerDownEvent event){
setState(() {
dragsTheScreen=false;
});
},
child: GoogleMap(
markers: markerItemsForShow.toSet(),
mapType: MapType.normal,
onMapCreated: onMapCreated,
onCameraMove: onCameraMove,
onCameraIdle: onCameraIdle,
initialCameraPosition:CameraPosition(tilt:25,target:LatLng(32.71,51.66), zoom: 5),
),
),
and in markers on tap callback when I am create them:
markerItemsForShow.add(Marker(
markerId:...,
position:...,
onTap: (){
setState(() {
dragsTheScreen=true;
});
}
));
I'm trying to add marker to my map widget based on the string in a Json file. However i have no idea how the marker thingy works after the .addMarker no longer applied. Can anyone please explain on it?
The markers: attribute in the Flutter_Google_maps widget now takes a Set<Marker>().
to add markers, first you should create an empty Set of type Marker and assign it to the markers: attribute in the google maps widget. Consequently, you append the desired Marker() to the created set using the add() method. Finally, you use setState() to rebuild the widget and display the updated Markers set on the UI.
Example:
class MapsScreen extends StatefulWidget {
#override
_MapsScreenState createState() => _MapsScreenState();
}
class _MapsScreenState extends State<MapsScreen> {
Completer<GoogleMapController> _mapsController = Completer();
Set<Marker> _myMarkers = Set<Marker>();
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
_myMakers.add(
markerId: MarkerId("current"),
position: LatLng(yourLatitude, yourLongitude),
);
setState((){});
)},
),
body: GoogleMap(
initialCameraPosition: _anyCameraPosition,
markers: _myMarkers,
onMapCreated: (GoogleMapController controller) {
_mapsController.complete(controller);
},
);
);
}
}
you have the option to use any state management pattern you prefer.
Using Google Maps for Flutter I've placed some markers on different places on the map. I have a separate RaisedButton on my Flutter app which I need to only be visible when one or more of those markers are currently visible on the map.
How can this be achieved? I've found a somewhat similar solution for Google Maps API but I need this for google_maps_flutter on Flutter.
LatLngBounds has specific method known as contains() which works along with GoogleMapController's getVisibleRegion().
From the official docs:
contains(LatLng point) → bool
Returns whether this rectangle contains the given LatLng.
Usage:
Completer<GoogleMapController> _controller = Completer();
static final CameraPosition _positionCenter = CameraPosition(
target: LatLng(40.730610, -73.935242),
zoom: 3.5,
);
Future<LatLngBounds> _getVisibleRegion() async {
final GoogleMapController controller = await _controller.future;
final LatLngBounds bounds = await controller.getVisibleRegion();
return bounds;
}
#override
Widget build(BuildContext context) {
void checkMarkers() async {
LatLngBounds bounds = await _getVisibleRegion();
Set<Marker> markers = Set<Marker>.of(markers.values);
markers.forEach((marker) {
print('Position: ${ marker.position } - Contains: ${ bounds.contains(marker.position) }');
});
}
return GoogleMap(
mapType: MapType.normal,
markers: Set<Marker>.of(markers.values),
initialCameraPosition: _positionCenter,
onCameraIdle: () {
checkMarkers();
},
onMapCreated: (GoogleMapController controller) async {
_controller.complete(controller);
checkMarkers();
},
);
}
google_maps_flutter is a developer preview at version 0.0.3. Please hang in there a bit until more functionality is introduced.