I'm a newbie in iOS development. I want to create a custom button with the same functionality as the default button (myLocationButton) in Google Maps SDK for iOS. Can I do that?
I can create the button but I don't know how to add action to track my current location and show the marker in the center of the screen. I'm using Swift 3.
Any help would be appreciated!
You could implement the action like so:
func gotoMyLocationAction(sender: UIButton)
{
guard let lat = self.mapView.myLocation?.coordinate.latitude,
let lng = self.mapView.myLocation?.coordinate.longitude else { return }
let camera = GMSCameraPosition.camera(withLatitude: lat ,longitude: lng , zoom: zoom)
self.mapView.animate(to: camera)
}
This center your map to your current position if they exists. Hope that helps.
Be sure the position detection on your GMSMapView is enabled
self.mapView.isMyLocationEnabled = true
Update Swift 4 for #Thomas answer, with GoogleMapSDK 2.7.0
func didTapMyLocationButton(for mapView: GMSMapView) -> Bool {
guard let lat = googleMapView.myLocation?.coordinate.latitude,
let lng = googleMapView.myLocation?.coordinate.longitude else { return false }
let camera = GMSCameraPosition.camera(withLatitude: lat ,longitude: lng , zoom: userMapZoom)
googleMapView.animate(to: camera)
return true
}
Related
What I'm attempting to do is run fitbounds on a set of markers, which works perfectly. However, I would like to center the map based on the user's location while keeping all markers within the map view. But I haven't found a solution. Is it possible? below is my code currently use to fit bounds.
func focusMapToShowAllMarkers() {
var bounds = GMSCoordinateBounds()
for location in locationsArray
{
let latitude = location.position.latitude
let longitude = location.position.longitude
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude:latitude, longitude:longitude)
//marker.map = self.viewMap
bounds = bounds.includingCoordinate(marker.position)
}
//bounds = bounds.includingCoordinate(CLLocationCoordinate2D(latitude:latitude, longitude:longitude))
let update = GMSCameraUpdate.fit(bounds, withPadding: 10)
viewMap.animate(with:update)
}
Using Google Maps iOS SDK, I want to be able to print the coordinates of a GMSMarker if long pressed on that particular marker.
I first get all of my coordinates from a dictionary and drop markers for all coordinates on the map:
func placeMapMarkers() {
for item in self.finalDictionary as [Dictionary<String, String>] {
let lat = item["lat"] as! String
let lon = item["lon"] as! String
let SpotLat = Double(lat)
let SpotLon = Double(lon)
let SpotLocation = CLLocationCoordinate2DMake(SpotLat!, SpotLon!)
DispatchQueue.main.async(execute: {
self.SpotMarker = GMSMarker(position: SpotLocation)
self.SpotMarker?.icon = self.imageWithImage(image: UIImage(named: "SpotIcon")!, scaledToSize: CGSize(width: 35.0, height: 35.0))
self.SpotMarker?.title = "Long press to navigate here"
self.SpotMarker?.map = self.mapView
})
longPress(mapView: self.mapView, didLongPressAtCoordinate: SpotLocation)
}
}
My longPress function call is in the above placeMapMarkers function itself, since I want to identify while placing markers itself if a particular marker has been long pressed (I could be wrong with my thinking here).
My longPress function is below.
//This is long Press function:-
func longPressView(mapView: GMSMapView!, didLongPressAtCoordinate coordinate: CLLocationCoordinate2D) {
//Here handle your long press on map marker like:-
print("long pressed at \(coordinate)")
}
The problem is that I am getting "long pressed at" all coordinates from the dictionary of coordinates.
I want to
place markers for all coordinates in a dictionary
long press on a particular marker
and print coordinates for only that particular marker which was long pressed.
How do I go about this? Had a look at the other solutions, wasn't able to work out much.
I looked through the GMSMapView API. There is a method called "didLongPressAtCoordinate" that passes in a CLLocationCoordinate2D, so I think you can use that to create a GMSMarker. See here
You have to implement the GMSMapViewDelegate, and you can call
func mapView(mapView: GMSMapView!, didLongPressAtCoordinate coordinate: CLLocationCoordinate2D) {
let marker = GMSMarker(position: coordinate)
marker.title = "Found You!"
marker.map = mapView
}
Hope this one helps :)
I have done this before. You basically have to convert the touch point on the map to a coordinate.
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
let uilpgr = UILongPressGestureRecognizer(target: self, action: #selector(userPerformedLongPress(gesture:)))
uilpgr.minimumPressDuration = 2.0
}
func userPerformedLongPress(gesture: UIGestureRecognizer) {
let touchPoint = gesture.location(in: mapView)
let newCoordinate: CLLocationCoordinate2D = mapView.convert(touchPoint, toCoordinateFrom: mapView)
let annotation = MKPointAnnotation()
annotation.coordinate = newCoordinate
annotation.title = "Location Selected"
annotation.subtitle = "Coordinate: \(round(1000*newCoordinate.longitude)/1000), \(round(1000*newCoordinate.latitude)/1000)"
mapView.addAnnotation(annotation)
print("Gesture recognized")
}
I'm using google maps to track
func ShowcurrentMarker()
{
currentlocationCoordinate = CLLocationCoordinate2DMake(LatestLocation.coordinate.latitude, LatestLocation.coordinate.longitude)
if(CurrentLocationMarker == nil)
{
CurrentLocationMarker = GMSMarker(position:currentlocationCoordinate)
CurrentLocationMarker.map = self.mapView
CurrentLocationMarker.icon = UIImage.init(named:"car_icon")
mapView.camera = GMSCameraPosition.camera(withTarget: CLLocationCoordinate2DMake(LatestLocation.coordinate.latitude, LatestLocation.coordinate.longitude), zoom: 15.0)
}
else
{
CATransaction.begin()
CATransaction.setAnimationDuration(2)
CurrentLocationMarker.position = currentlocationCoordinate
CurrentLocationMarker.rotation = CLLocationDirection.abs(LatestLocation.course)
mapView.camera = GMSCameraPosition.camera(withTarget: CLLocationCoordinate2DMake(LatestLocation.coordinate.latitude, LatestLocation.coordinate.longitude), zoom:mapView.camera.zoom)
CATransaction.commit()
}
}
Here is my working code. Now I want my car always to keep on north facing like navigation app.
How can I do that ?
SWIFT 3.0
MKMAPVIEW
iOS
Note : - (Integrated AppleMap ,Not working with GoogleMap)
I have done the following :
Implemented map and Added custom Image to User Location Annotation
When map open , it shows User Location at right Place
My Requirement :
When User Move into different direction staying at same place (or
different place) the pin (at current location) should automatically
point the direction in which user points.
E.g : If Boat is showing at User Location position and its pointing toward North but if user move toward West then boat (User Location Pin) also should point to that direction.
Tried with following Code :
//MARK:Change Direction Methods
func angle(fromCoordinate first: CLLocationCoordinate2D, toCoordinate second: CLLocationCoordinate2D) -> Float {
let deltaLongitude = second.longitude - first.longitude
let deltaLatitude = second.latitude - first.latitude
let angle = (.pi * 0.5) - atan(deltaLatitude / deltaLongitude)
if deltaLongitude > 0 {
return Float(angle)
}
else if deltaLongitude < 0 {
return Float(angle) + .pi
}
else if deltaLatitude < 0 {
return .pi
}
return 0.0
}
//Animate direction of User Location
func animateUserLocation() {
//Old Coordinate (PLAT - Previous Lat , PLON - Previous Long)
let oldLocation = CLLocationCoordinate2D(latitude: UserDefaults.standard.value(forKey: "PLAT") as! CLLocationDegrees, longitude: UserDefaults.standard.value(forKey: "PLON") as! CLLocationDegrees)
//New Coordinate (PLAT - Current Lat , PLON - Current Long)
let newLocation = CLLocationCoordinate2D(latitude: UserDefaults.standard.value(forKey: "LAT") as! CLLocationDegrees, longitude: UserDefaults.standard.value(forKey: "LON") as! CLLocationDegrees)
let getAngle = angle(fromCoordinate:oldLocation, toCoordinate:newLocation)
var myAnnotation : RestaurantAnnotation?
if annotationArray.count > 0{
myAnnotation = annotationArray[0]
}
else {
return
}
UIView.animate(withDuration: 2, animations: {() -> Void in
myAnnotation?.coordinate = newLocation
let annotationView = self.map.view(for: myAnnotation!)
annotationView?.transform = CGAffineTransform(rotationAngle: CGFloat(getAngle))
})
//Save Previous lat long
UserDefaults.standard.set(UserDefaults.standard.value(forKey: "LAT"), forKey: "PLAT")
UserDefaults.standard.set(UserDefaults.standard.value(forKey: "LON"), forKey: "PLON")
UserDefaults().synchronize()
}
Called animateUserLocation method from didUpdateLocation Method but no Luck.
Kindly share your suggestion what i am doing wrong . Thanks in advance.
Understanding iOS's location concepts completely helps to resolve any issue regarding AppleMap.
To move map Pin or AnnotationView , we can use the CoreLocation framework which outputs data related to the users current location.
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
var locationManager:CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.startUpdatingHeading()
}
func locationManager(manager: CLLocationManager!, didUpdateHeading heading: CLHeading!) {
// This will print out the direction the device is heading
println(heading.magneticHeading) }
}
}
In the above example, "heading.magneticHeading" will output a value representing the direction the device is pointed at.
0 means north
90 means east
180 means south
270 means west
everything else in between
The next step is to use those values and rotate your AnnotationView or Pin accordingly.
CGAffineTransformMakeRotation can help with this.
For example if you want to rotate to imageview to point to northeast, which would require a degree value of 45, your code might look something like this.
float degrees = 45
imageView.transform = CGAffineTransformMakeRotation(degrees * M_PI/180)
Just be aware that CGAffineTransformMakeRotation() expects a radian value, in the example above we've converted degrees to radians by multiplying degrees with the number of half circles.
Following links really helpful :
https://stackoverflow.com/a/7634232/3400991
Finally Resolved my issue. Hope this complete answer helps other too.
I am displaying a marker in a particular place, along with displaying the current address in the address label on Google Maps.
Now, I want to change the location by moving the Google Map, but the problem is that when I am moving the map, I should simultaneously move the marker along with the map, and I should display the address of that location in the address label.
How can I do that?
I tried this:
let destinationMarker = GMSMarker(position: self.destinationLocation.coordinate)
let image = UIImage(named:"sourcemarker")
destinationMarker.icon = image
destinationMarker.draggable = true
destinationMarker.map = self.viewMap
//viewMap.selectedMarker = destinationMarker
destinationMarker.title = "hi"
destinationMarker.userData = "changedestination"
func mapView(mapView: GMSMapView, didEndDraggingMarker marker: GMSMarker)
{
if marker.userData as! String == "changedestination"
{
self.destinationLocation = CLLocation(latitude: marker.position.latitude, longitude: marker.position.longitude)
self.destinationCoordinate = self.destinationLocation.coordinate
//getAddressFromLatLong(destinationCoordinate)
}
}
// UpdteLocationCoordinate
func updateLocationoordinates(coordinates:CLLocationCoordinate2D) {
if destinationMarker == nil
{
destinationMarker = GMSMarker()
destinationMarker.position = coordinates
let image = UIImage(named:"destinationmarker")
destinationMarker.icon = image
destinationMarker.map = viewMap
destinationMarker.appearAnimation = kGMSMarkerAnimationPop
}
else
{
CATransaction.begin()
CATransaction.setAnimationDuration(1.0)
destinationMarker.position = coordinates
CATransaction.commit()
}
}
// Camera change Position this methods will call every time
func mapView(mapView: GMSMapView, didChangeCameraPosition position: GMSCameraPosition) {
let destinationLocation = CLLocation()
if self.mapGesture == true
{
destinationLocation = CLLocation(latitude: position.target.latitude, longitude: position.target.longitude)
destinationCoordinate = destinationLocation.coordinate
updateLocationoordinates(destinationCoordinate)
}
}
Update for Swift 4:
First you need to conform with the GMSMapViewDelegate:
extension MapsVC: GMSMapViewDelegate{
And then set your VC as the delegate of viewMap in the viewDidLoad()
viewMap.delegate = self
After that you just need to use the following method to get updates from the camera position and set that as the new position for the marker:
func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {
destinationMarker.position = position.target
print(destinationMarker.position)
}
There is one trick that can help you out here. Instead of using a GMSMarker here, put an image pointing to the center, over your Google MapView.
You can easily find the coordinates of Map's center using this :
double latitude = mapView.camera.target.latitude;
double longitude = mapView.camera.target.longitude;
Or this
GMSCoordinateBounds *bounds = nil;
bounds = [[GMSCoordinateBounds alloc] initWithRegion: visibleRegion];
CLLocationCoordinate2D centre = CLLocationCoordinate2DMake(
(bounds.southWest.latitude + bounds.northEast.latitude) / 2,
(bounds.southWest.longitude + bounds.northEast.longitude) / 2);
Now you can get the location address by using Geocoding API by google.
Here is the reference :
https://developers.google.com/maps/documentation/ios-sdk/reference/interface_g_m_s_geocoder
You can refresh Address when this delegate method is called :
- (void) mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position
Hope this helps.
Based from Release Notes made in Maps SDK for IOS, changing a markers position will cause the marker to animate to the new location.
To resolve this, you may use new features for GMSMarker as stated in Release Version 1.5 such as:
Markers can be made draggable using the draggable property, and new drag delegate methods have been added to GMSMapViewDelegate. (Issue 4975)
Added GMSMarkerLayer, a custom CALayer subclass for GMSMarker that supports animation of marker position and rotation. (Issue 4951, Issue 5743)
In addition to that, this post in GitHub - GoogleMapsAnimationGlitch
and this SO post - How to smoothly move GMSMarker along coordinates in Objective c
might also help.
objc_sync_enter(self)
CATransaction.begin()
CATransaction.setCompletionBlock { [weak self] in
guard let `self` = self else { return }
DispatchQueue.main.delay(0.5) {
self.mapViewService.setCenter(location.coordinate, animate: true, zoom: nil)
}
objc_sync_exit(self)
}
CATransaction.setAnimationDuration(vm.continunousLocationUpdateTimeInterval)
self.mapViewService.moveMarker(position: location.coordinate, marker: userMarker)
CATransaction.commit()
the code above is useful to me, the moveMarker method just packaged the code marker.position = newCoordinate