This is all my code. I want it to be able to search for places from lat , lng , and if lat,lng is not there, it will search for places from names. But now it's like when searching for a place from the name. In the part where the name is converted to lat,lng it's correct but my marker appears in the middle of the sea
LatLng centerMap = LatLng(13.730452094709594, 100.64180575311175);
#override
void initState() {
findLocation();
super.initState();
}
void findLocation() async {
var lat = double.tryParse(searchitems[0].address![widget.index].latitude.toString());
var lng = double.tryParse(searchitems[0].address![widget.index].longitude.toString());
if (lat != null && lng != null) {
centerMap = LatLng(lat, lng);
} else {
var name = searchitems[0].name;
var addr = '${searchitems[0].address![widget.index].addr1!}, ${searchitems[0].address![widget.index].thanon!}, ${searchitems[0].address![widget.index].tambon!}, ${searchitems[0].address![widget.index].province!}';
var addresses = await Geocoder.local.findAddressesFromQuery(addr);
var first = addresses.first;
centerMap = LatLng(first.coordinates.latitude!, first.coordinates.longitude!);
print("Location not found, searching for name: $name and address: $addr");
}
print("map:$centerMap");
}
GoogleMap(
initialCameraPosition: CameraPosition(
target: centerMap,
zoom: 16.0,
),
You can add a controller in Google maps, then when you call the API and get new lat long, you can animate camera to that position like this:
Future<void> _goToNewPosition() async {
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(_kLake));
}
There's also an example on the official package, you can check it out by this link
Related
I'm a total noob with flutter and I'm trying to create an app that shows me some markers on a map pointing the location of the soccer fields and only this.
enter image description here
Currently i have the google map marks all the places nearby. I did this using the google Nearvy places API. So I need it to only mark the nearby soccer fields, but this option does not appear in the type section.
This is the code that I use to use the google api. As u seen in the url, the word soccer in type does not work.
Future<dynamic> getPlaceDetails(LatLng coords, int radius) async {
var lat = coords.latitude;
var lng = coords.longitude;
final String url =
'https://maps.googleapis.com/maps/api/place/nearbysearch/json?&location=$lat,$lng&radius=$radius&type=soccer&key=$key';
var response = await http.get(Uri.parse(url));
var json = convert.jsonDecode(response.body);
return json;
}
This is the method I use to mark the nearvy places
void maracaCanchas() {
if (_debounce?.isActive ?? false) _debounce?.cancel();
_debounce = Timer(Duration(seconds: 2), () async {
var placesResult =
await MapServices().getPlaceDetails(tappedPoint, radiusValue.toInt());
List<dynamic> placesWithin = placesResult['results'] as List;
allFavoritePlaces = placesWithin;
tokenKey = placesResult['next_page_token'] ?? 'none';
_markers = {};
placesWithin.forEach((element) {
_setNearMarker(
LatLng(element['geometry']['location']['lat'],
element['geometry']['location']['lng']),
element['name'],
element['types'],
element['business_status'] ?? 'not available',
);
});
_markersDupe = _markers;
pressedNear = true;
_setLocationMarker();
});
}
Please help me.
I am trying to mark only soccer fields on the map, but it brings me all the places
I'm currently developing a flutter a taxi application and I want to use MapQuest API for the applications to get the locations names and to draw route from one point to another.
The problem is that calling the API and getting the locations works fine but the route is showing on the map in a really weird way.
Here is the provider code for calling the API and getting the route locations points:
class MapQuestDataProvider {
Future<MapQuestDirection> getDirections(
LatLng Source, LatLng Destination) async {
try {
MapQuestDirection result = MapQuestDirection(locations: []);
var aPIKey = "[API_KEY]";
var url =
"https://www.mapquestapi.com/directions/v2/optimizedroute?key=$aPIKey&json={\"locations\":[\"${Source.latitude},${Destination.longitude}\",\"${Destination.latitude},${Source.longitude}\"]}";
var uri = Uri.parse(url);
final response = await http.get(uri);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
var route = data["route"];
var legs = route["legs"];
var zero = legs[0];
var maneuvers = zero["maneuvers"] as List;
for (var element in maneuvers) {
var startPoint = element["startPoint"];
var lat = startPoint["lat"];
var lng = startPoint["lng"];
result.locations.add(LatLng(lat, lng));
}
return result;
} else {
throw Exception('Failed to load Locations');
}
} catch (e) {
print("Exception throuwn $e");
throw e;
}
}
}
Here is the code for my Map Widget:
class MapWidget extends StatefulWidget {
MapWidget(
{Key? key,
this.currentLocation,
required this.onTab,
required this.markers,
this.endLocation,
required this.polylines})
: super(key: key);
LatLng? currentLocation;
void Function(LatLng) onTab;
Set<Marker> markers = {};
LatLng? endLocation;
Map<PolylineId, Polyline> polylines = {};
#override
State<MapWidget> createState() => _MapWidgetState();
}
class _MapWidgetState extends State<MapWidget> {
GoogleMapController? mapController;
final defaultMapZooming = 18.0;
#override
Widget build(BuildContext context) {
return Container(child: mapView(context));
}
Widget mapView(BuildContext context) {
if (mapController != null && widget.currentLocation != null) {
mapController!.animateCamera(CameraUpdate.newLatLngZoom(
LatLng(widget.currentLocation!.latitude,
widget.currentLocation!.longitude),
defaultMapZooming));
}
var map = GoogleMap(
onMapCreated: onMapCreated,
zoomControlsEnabled: false,
myLocationEnabled: false,
mapType: MapType.normal,
onLongPress: (loc) {
widget.onTab(loc);
},
markers: widget.markers,
polylines: widget.polylines.values.toSet(),
minMaxZoomPreference: const MinMaxZoomPreference(12, 25),
initialCameraPosition: CameraPosition(
target: getLocationOrDefault(),
zoom: defaultMapZooming,
),
onCameraMove: (CameraPosition cameraPosition) {
print("ZOOOOOOOOOOOOOOOOOOOM IS : " + cameraPosition.zoom.toString());
},
);
return map;
}
onMapCreated(GoogleMapController controller) {
mapController = controller;
}
getLocationOrDefault() {
return widget.currentLocation ??
const LatLng(21.215415017175165, 72.8879595194489);
}
}
And Here is the code that gets called by placing a new marker on the map which draws the polygon that will be sent to the Map Widget after state update:
SetPathFromMapQuestData(List<LatLng> Locations) {
PolylinePoints polylinePoints = PolylinePoints();
Set<Marker> markers = Set(); //markers for google map
LatLng startLocation = this.startLocation!;
LatLng endLocation = this.endLocation!;
double distance = 0.0;
List<LatLng> polylineCoordinates = [];
//polylineCoordinates.add(this.startLocation!);
Locations.forEach((LatLng point) {
polylineCoordinates.add(point);
});
polylineCoordinates.insert(0, this.startLocation!);
polylineCoordinates.add(this.endLocation!);
PolylineId id = PolylineId("poly");
var poly = GetPloylineId(polylineCoordinates, id);
polylines[id] = poly;
setState(() {
this.polylines = polylines;
});
}
Polyline GetPloylineId(List<LatLng> polylineCoordinates, PolylineId id) {
Polyline polyline = Polyline(
polylineId: id,
color: Colors.deepPurpleAccent,
points: polylineCoordinates,
width: 8,
);
return polyline;
}
This is the result:
The Result Map Image
After working for hours I moved to MapBox and it works perfectly.
Here is the link for the Api:
https://docs.mapbox.com/android/navigation/guides/
I have some code written in dart where I use the provider package to update the location of a pin on a map. What I would like it to do is have the initial location be equal to the user's current position and then if they drag the pin it will be updated to wherever the pin is dropped.
My problem is that the initial location variable needs to Future<LatLng>, however, when I update the location it ends up being just LatLng and I cannot assign it to the _location variable.
class LocationProvider with ChangeNotifier {
Future<LatLng> _location = LocationService().getLocation();
// Error here, wants it to be Future<LatLng>
LatLng get location => _location;
void calculateNewLocation(oldLocation, zoom, offset) {
var newPoint = const Epsg3857().latLngToPoint(oldLocation, zoom) +
CustomPoint(offset.dx, offset.dy);
LatLng? newLocation = const Epsg3857().pointToLatLng(newPoint, zoom);
// Error here again for the same reason
_location = newLocation ?? _location;
notifyListeners();
}
}
How do I make it so that I can assign both of these values to _location?
You can simply have a method for that in provider file
class LocationProvider with ChangeNotifier {
LatLng? _location;
LatLng? get location => _location;
Future<void> initializeLocation() async {
_location = await LocationService().getLocation();
notifyListeners();
}
void calculateNewLocation(oldLocation, zoom, offset) {
var newPoint = const Epsg3857().latLngToPoint(oldLocation, zoom) +
CustomPoint(offset.dx, offset.dy);
LatLng? newLocation = const Epsg3857().pointToLatLng(newPoint, zoom);
_location = newLocation ?? _location;
notifyListeners();
}
}
Then, you'll have to call initializeLocation when you want it to be initialized, like:
Future<void>? _myFuture;
final _provider = Provider.of<LocationProvider>(listen: false);
_myFuture = _provider.initializeLocation();
and then in FutureBuilder, provide _myFuture in future
PS: ? can be excluded if you're not using dart in null safe mode
Based on your code,
LocationService().getLocation() returns a future, so you have to either await/async or use then().
try these
Future<LatLng> _location = LocationService().getLocation();
LatLng get location = await _location; // put this in a separate method with async keyword
or
LocationService().getLocation().then((value) { location = value } );
I have project using MapBox to show address location in map. I have latitude and longitude (-6.192461941069894,106.97593586545025) like this , i want if i click right on marker, i want open Google Maps Apps based on latitude and longitude i have.
But the problem , i can't open google maps after click symbol because latitude&longitude after click maps not same with latitude&longitude i have.
Logic Source Code
onMapClick: (point, latlng) {
if (latlng.latitude == latitude && latlng.longitude == longitude) {
launchGoogleMaps(latitude: latitude, longitude: longitude);
}
print(
"From Map ${latlng.latitude} |${latlng.latitude} \nFrom Server $latitude||$longitude \n\n");
},
I think when clicking points on the map are close to each other, I can directly open the Google Maps application. How i can do this ?
Full Source Code
class ExampleMapBox extends StatefulWidget {
#override
_ExampleMapBoxState createState() => _ExampleMapBoxState();
}
class _ExampleMapBoxState extends State<ExampleMapBox> {
MapboxMapController mapController;
double latitude, longitude;
#override
void initState() {
super.initState();
latitude = -6.192461941069894;
longitude = 106.97593586545025;
}
void _onMapCreated(MapboxMapController mapboxMapController) {
mapController = mapboxMapController;
}
#override
Widget build(BuildContext context) {
return MapboxMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(target: LatLng(latitude, longitude), zoom: 10),
onStyleLoadedCallback: () => addSymbol(mapController),
onMapClick: (point, latlng) {
if (latlng.latitude == latitude && latlng.longitude == longitude) {
launchGoogleMaps(latitude: latitude, longitude: longitude);
}
print(
"From Map ${latlng.latitude} |${latlng.latitude} \nFrom Server $latitude||$longitude \n\n");
},
);
}
void addSymbol(MapboxMapController mapBoxController) {
mapBoxController.addSymbol(
SymbolOptions(
geometry: LatLng(latitude, longitude),
iconImage: "assets/images/custom-icon.png",
iconSize: 2,
),
);
}
void launchGoogleMaps({#required double latitude, #required double longitude}) async {
String googleUrl = 'https://www.google.com/maps/search/?api=1&query=$latitude,$longitude';
if (await canLaunch(googleUrl)) {
await launch(googleUrl);
} else {
throw 'Could Not Open The Map';
}
}
}
Generating the exact same coordinates up to a 15 digit precision by clicking on a map is far from possible.
I would recommend to compute the deviation in latitude and longitude and fire the launchGoogleMaps function when the deviation is below a certain threshold. Please try something like the below:
deviation_lat = (latlng.latitude - latitude) * (latlng.latitude - latitude);
deviation_lon = (latlng.longitude - longitude) * (latlng.longitude - longitude);
if (deviation_lat < 1 && deviation_lon < 1) {
launchGoogleMaps(latitude: latitude, longitude: longitude);
}
aFunction(Symbol symbol){
// code goes here
}
void addSymbol(MapboxMapController mapBoxController) {
mapBoxController.addSymbol(
SymbolOptions(
geometry: LatLng(latitude, longitude),
iconImage: "assets/images/custom-icon.png",
iconSize: 2,
),
);
mapBoxController.onSymbolTapped.add(aFunction); // This is a callback for symbols when tapped.
}
You can try this.
I've implemented a reliable way of getting user lat,long coordinates in an app I'm creating, but can't seem to turn these coordinates into a placemark.
I'd also like to figure out what I need to use to print this data.
This is what I'm trying to get this data with:
List<Placemark> place = [];
void _getPlace() async {
List<Placemark> newPlace = await _geolocator.placemarkFromCoordinates(_position.latitude, _position.longitude);
print(newPlace);
setState(() {
place = newPlace;
});
}
Thanks
Edit:
After CopsOnRoad's response, I'm getting this error:
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception:
NoSuchMethodError: The method 'placemarkFromCoordinates' was called on null.
Receiver: null
Tried calling: placemarkFromCoordinates(51.4998, -0.129)
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
#1 _NearbyPageState._getPlace
package:tr/pages/nearby.dart:128
<asynchronous suspension>
#2 _NearbyPageState._controlCard.<anonymous closure>
package:tr/pages/nearby.dart:629
#3 GestureRecognizer.invokeCallback
package:flutter/…/gestures/recognizer.dart:182
#4 TapGestureRecognizer._checkUp
package:flutter/…/gestures/tap.dart:365
#5 TapGestureRecognizer.acceptGesture
package:flutter/…/gestures/tap.dart:312
#6 GestureArenaManager.sweep
package:flutter/…/gestures/arena.dart:156
#7 _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent
package:flutter/…/gestures/binding.dart:222
#8 _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (p<…>
Update:
Use geocoding
import 'package:geocoding/geocoding.dart';
List<Placemark> placemarks = await placemarkFromCoordinates(52.2165157, 6.9437819);
Old solution:
You are already there, extra stuff that you need is:
String _address = ""; // create this variable
void _getPlace() async {
List<Placemark> newPlace = await _geolocator.placemarkFromCoordinates(_position.latitude, _position.longitude);
// this is all you need
Placemark placeMark = newPlace[0];
String name = placeMark.name;
String subLocality = placeMark.subLocality;
String locality = placeMark.locality;
String administrativeArea = placeMark.administrativeArea;
String postalCode = placeMark.postalCode;
String country = placeMark.country;
String address = "${name}, ${subLocality}, ${locality}, ${administrativeArea} ${postalCode}, ${country}";
print(address);
setState(() {
_address = address; // update _address
});
}
Placemark has been removed from geolocator starting from version 6.0.0 and moved to geocoding.
Starting from version 6.0.0 the geocoding features (placemarkFromAddress and placemarkFromCoordinates) are no longer part of the geolocator plugin. We have moved these features to their own plugin: geocoding. This new plugin is an improved version of the old methods.
To translate latitude and longitude into an address with geocoding use
List<Placemark> placemarks = await placemarkFromCoordinates(52.2165157, 6.9437819);
Use pub.dev flutter_geocoding
https://pub.dev/packages/flutter_geocoding
OR
I have used swift 'GMSGeocoder' and java 'android.location.Geocoder' and applied it to flutter.I think it is more efficient than the library Geocode in pub.dev.
My example code
Geocode library java and swift add by yourself
java
#Override
public void configureFlutterEngine(#NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), "samples.flutter.dev/latlng")
.setMethodCallHandler(
(call, result) -> {
double lat = call.argument("lat");
double lng = call.argument("lng");
result.success("return value lat and lng");
}
);
}
swift
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "samples.flutter.dev/latlng",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: #escaping FlutterResult) -> Void in
// Note: this method is invoked on the UI thread.
guard call.method == "latlng" else {
result(FlutterMethodNotImplemented)
return
}
self?.latlng(call,result: result)
})
GMSServices.provideAPIKey("")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func latlng(_ call: FlutterMethodCall,result:FlutterResult) {
if let args = call.arguments as? Dictionary<String, Any>,
let lat = args["lat"] as? Double ,let lng = args["lng"] as? Double {
result("return latlng result" )
} else {
result(FlutterError.init(code: "bad args", message: nil, details: nil))
}
}
flutter
Future<void> _getBatteryLevel(double a, double b) async {
String latlng;
try {
final String result = await const MethodChannel('samples.flutter.dev/latlng').invokeMethod(
'latlng', <String, dynamic>{"lat": a, "lng": b});
latlng = result;
} on PlatformException catch (e) {
latlng = "Failed to get latlng level: '${e.message}'.";
}
}
first, you have include lib -geolocator: ^3.0.1 in pubspec.yaml
///Get current location
Geolocator _geolocator = Geolocator();
String latitude = "";
String longitude = "";
String address = "";
Try this solution -
///Call this function
_fetchLocation() async {
Position position = await _geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best);///Here you have choose level of distance
latitude = position.latitude.toString() ?? '';
longitude = position.longitude.toString() ?? '';
var placemarks = await _geolocator.placemarkFromCoordinates(position.latitude, position.longitude);
address ='${placemarks.first.name.isNotEmpty ? placemarks.first.name + ', ' : ''}${placemarks.first.thoroughfare.isNotEmpty ? placemarks.first.thoroughfare + ', ' : ''}${placemarks.first.subLocality.isNotEmpty ? placemarks.first.subLocality+ ', ' : ''}${placemarks.first.locality.isNotEmpty ? placemarks.first.locality+ ', ' : ''}${placemarks.first.subAdministrativeArea.isNotEmpty ? placemarks.first.subAdministrativeArea + ', ' : ''}${placemarks.first.postalCode.isNotEmpty ? placemarks.first.postalCode + ', ' : ''}${placemarks.first.administrativeArea.isNotEmpty ? placemarks.first.administrativeArea : ''}';
print("latitude"+latitude);
print("longitude"+longitude);
print("adreess"+address);
}
try {
await Geolocator()
.placemarkFromCoordinates(value[0], value[1])
.then((result) {
Placemark placeMark = result[0];
String name = placeMark.name;
String subLocality = placeMark.subLocality;
String locality = placeMark.locality;
String administrativeArea = placeMark.administrativeArea;
String postalCode = placeMark.postalCode;
String country = placeMark.country;
String address =
"${name}, ${subLocality}, ${locality}, ${administrativeArea} ${postalCode}, ${country}";
print(address);
});
} on PlatformException catch (e) {
print(e);
}
With Geolocator Plugin new version (from version 6.0.0). Geocoding features (placemarkFromAddress and placemarkFromCoordinates) are no longer part of the geolocator plugin. This method have moved these features to their own plugin: geocoding
Future getLatAndlong() async{
cl = await Geolocator.getCurrentPosition().then((value)=>value);
lat = cl.latitude;
long = cl.longitude;
_kGooglePlex = CameraPosition(
target: LatLng(lat,long),
zoom:14
);
List<Placemark> placemarks = await placemarkFromCoordinates(
lat, long);
print("country"+placemarks[0].country!);
print("area"+placemarks[0].administrativeArea!);
print("locality"+placemarks[0].locality!);
print("sublocality"+placemarks[0].subLocality!);
print("postlocality"+placemarks[0].postalCode!);
print("street"+placemarks[0].street!);
setState(() {
countrycurrent = placemarks[0].country!;
localcurrent = placemarks[0].administrativeArea!;
madinacurrent = placemarks[0].subLocality!;
curren=countrycurrent+","+localcurrent+","+madinacurrent;
});
mymarker.add(
Marker(
infoWindow: InfoWindow(
title: placemarks[0].country! + "," +
placemarks[0].administrativeArea! +
"," + placemarks[0].locality!
),
draggable: true,
icon:
BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueOrange),
markerId: MarkerId("4"),
position: LatLng(lat, long)),
);}