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.
Related
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
Can someone please teach me how to get the longitude and latitude from a given address using geocode in flutter?
I want to get the coordinates to use them as markers on the map.
Update: Here is my code:
class _PlaceInfoState extends State {
late double _latitude;
late double _longitude;
#override
void initState(){
getLatLon();
super.initState();
}
Future <void> getLatLon() async {
GeoCode geoCode = GeoCode();
try {
Coordinates coordinates = await geoCode.forwardGeocoding(address: "${widget.packageModel.destination}");
final lat = coordinates.latitude!;
final lon = coordinates.longitude!;
setState((){
_latitude = lat;
_longitude = lon;
});
} catch (e) {
print(e);
}
}
This is where I try to put the show coordinates on the map but it doesn't seem to show the map, it said that the _latitude has not been initialized:
//Location
Container(
padding: EdgeInsets.only(top: 20),
height: MediaQuery.of(context).size.height / 2.5,
width: MediaQuery.of(context).size.width,
child: GoogleMap(
scrollGesturesEnabled: true,
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(_latitude, _longitude),
zoom: 14
)
),
),
The example from the documentation:
import 'package:geocode/geocode.dart';
void main() async {
GeoCode geoCode = GeoCode();
try {
Coordinates coordinates = await geoCode.forwardGeocoding(
address: "532 S Olive St, Los Angeles, CA 90013");
print("Latitude: ${coordinates.latitude}");
print("Longitude: ${coordinates.longitude}");
} catch (e) {
print(e);
}
}
Do you have further questions?
I am passing select latitude and longitude from google maps to my flutter app's another screen where I am calculating the distance between 2 locations.
I've got the values coming fine but there's this widget can't be accessed in an initializer issue coming.
I'm using google maps and I've to pass the widget.lat widget.long values to the userLocation marker.
I'm using this tutorial's code by the way
Get distance between locations
Here's my code
class CalculateDistance extends StatefulWidget {
const CalculateDistance({super.key, required this.lang, required this.lat});
final double lang;
final double lat;
#override
// ignore: library_private_types_in_public_api
_CalculateDistanceState createState() => _CalculateDistanceState();
}
class _CalculateDistanceState extends State<CalculateDistance> {
GoogleMapController? mapController; //contrller for Google map
PolylinePoints polylinePoints = PolylinePoints();
String googleAPiKey = "YOUR_API_KEY";
Set<Marker> markers = {}; //markers for google map
Map<PolylineId, Polyline> polylines = {}; //polylines to show direction
LatLng storeLocation =
const LatLng(-30.600164342582726, 23.508854043469647); // Store location
// This is where I can't use the passed values
LatLng userLocation = LatLng(widget.lat, widget.lang); // User location
double distance = 0.0;
#override
void initState() {
markers.add(Marker(
//add start location marker
markerId: MarkerId(storeLocation.toString()),
position: storeLocation, //position of marker
infoWindow: const InfoWindow(
//popup info
title: 'Store Location',
snippet: 'Store Marker',
),
icon: BitmapDescriptor.defaultMarker, //Icon for Marker
));
markers.add(Marker(
//add distination location marker
markerId: MarkerId(userLocation.toString()),
position: userLocation, //position of marker
infoWindow: const InfoWindow(
//popup info
title: 'User Location',
snippet: 'User Marker',
),
icon: BitmapDescriptor.defaultMarker, //Icon for Marker
));
getDirections(); //fetch direction polylines from Google API
super.initState();
}
getDirections() async {
List<LatLng> polylineCoordinates = [];
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
googleAPiKey,
PointLatLng(storeLocation.latitude, storeLocation.longitude),
PointLatLng(userLocation.latitude, userLocation.longitude),
travelMode: TravelMode.driving,
);
if (result.points.isNotEmpty) {
for (var point in result.points) {
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
}
} else {
print(result.errorMessage);
}
//polulineCoordinates is the List of longitute and latidtude.
double totalDistance = 0;
for (var i = 0; i < polylineCoordinates.length - 1; i++) {
totalDistance += calculateDistance(
polylineCoordinates[i].latitude,
polylineCoordinates[i].longitude,
polylineCoordinates[i + 1].latitude,
polylineCoordinates[i + 1].longitude);
}
print(totalDistance);
setState(() {
distance = totalDistance;
});
//add to the list of poly line coordinates
addPolyLine(polylineCoordinates);
}
addPolyLine(List<LatLng> polylineCoordinates) {
PolylineId id = const PolylineId("poly");
Polyline polyline = Polyline(
polylineId: id,
color: Colors.deepPurpleAccent,
points: polylineCoordinates,
width: 8,
);
polylines[id] = polyline;
setState(() {});
}
double calculateDistance(lat1, lon1, lat2, lon2) {
var p = 0.017453292519943295;
var a = 0.5 -
cos((lat2 - lat1) * p) / 2 +
cos(lat1 * p) * cos(lat2 * p) * (1 - cos((lon2 - lon1) * p)) / 2;
return 12742 * asin(sqrt(a));
}
// Scaffold ahead
Declare this LatLng with late keyword as a member of _CalculateDistanceState class:
class _CalculateDistanceState extends State<CalculateDistance> {
late LatLng _userLocation;
(...)
}
Then in the initState you will have access to the widget:
void initState() {
super.initState();
_userLocation = LatLng(widget.lat, widget.lang);
(...)
}
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 list of Latlng that contains on list of places lat&lng
and I want check my current location is near of any of these places by 1 kilo
static locationListen() async {
List<LatLng> savedPlace = [
LatLng(12.333,-344.2222),
LatLng(1.333,-14.2222),
LatLng(2.333,-24.2222),
];
var locationOptions =
LocationOptions(accuracy: LocationAccuracy.high, distanceFilter: 10);
Geolocator().getPositionStream(locationOptions).listen(
(Position position) {
LatLng currentLatlng = LatLng(position.latitude,position.longitude);
//check this if is this currentLatlng near by 1 kilo from
// any of those places savedPlace
},
);
}
I see you're using Geolocator plugin:
Take a try like that:
double distanceInMeters = await Geolocator().distanceBetween(lat1, lng1, lat2, lng2);
you can use plugin call latlong 0.6.1
dependencies:
latlong: ^0.6.1
import 'package:latlong/latlong.dart';
and try it
Geolocator().getPositionStream(locationOptions).listen( (Position position) {
LatLng currentLatlng = LatLng(position.latitude,position.longitude);
savedPlace.forEach((savedlatlong) {
int km = distance.as(LengthUnit.Kilometer,currentLatlng,savedlatlong);
// do whatever you wanna do with km
});
},);