Skip to main content

Draggable Marker and Drawing the routes between them using Google Maps | IOS | Swift

This blog is about how we can make the marker draggable and get the current location from it and to draw the routes between them.

For that we have to install the pods of Google maps from developer.google.com.
Then we have to add the following 
  pod 'GoogleMaps'
  pod 'GooglePlaces'
  pod 'GooglePlacesAPI'
  pod 'SwiftyJSON'

And we have to save the pods into the pod file.
Then, we have to install all the pods through terminal.

Again we have to make the outlet for textfield and button as discussed below.
2 TextField and 3 Buttons.

Hope you will enjoy the coding. Happy coding.!


import UIKit
import GoogleMaps
import GooglePlaces
import SwiftyJSON
import Alamofire

enum Location {
case startLocation
case destinationLocation
}

class ViewController: UIViewController , GMSMapViewDelegateCLLocationManagerDelegate {
@IBOutlet weak var googleMaps: GMSMapView!
@IBOutlet weak var startLocation: UITextField!
@IBOutlet weak var destinationLocation: UITextField!

var locationManager = CLLocationManager()
var locationSelected = Location.startLocation
    var polyline = GMSPolyline()
    var locationStart = CLLocation()
var locationEnd = CLLocation()
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startMonitoringSignificantLocationChanges()
//Your map initiation code
let camera = GMSCameraPosition.camera(withLatitude: 28.524555, longitude: 77.275111, zoom: 6.0)
self.googleMaps.camera = camera
self.googleMaps.delegate = self
self.googleMaps?.isMyLocationEnabled = true
self.googleMaps.settings.myLocationButton = true
self.googleMaps.settings.compassButton = true
self.googleMaps.settings.zoomGestures = true
}
// MARK: function for create a marker pin on map
func createMarker(titleMarker: String, iconMarker: UIImage, latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(latitude, longitude)
        marker.isDraggable=true
marker.title = titleMarker
marker.icon = iconMarker
marker.map = googleMaps
}
//MARK: - Location Manager delegates
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error to get location : \(error)")
}
    
    
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
// let camera = GMSCameraPosition.camera(withLatitude: (location?.coordinate.latitude)!, longitude: (location?.coordinate.longitude)!, zoom: 17.0)
let locationMobi = CLLocation(latitude: 28.524555, longitude: 77.275111)
drawPath(startLocation: location!, endLocation: locationMobi)
//self.googleMaps?.animate(to: camera)
self.locationManager.stopUpdatingLocation()
}
// MARK: - GMSMapViewDelegate
func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {
googleMaps.isMyLocationEnabled = true
}
func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
googleMaps.isMyLocationEnabled = true
if (gesture) {
mapView.selectedMarker = nil
}
}
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
googleMaps.isMyLocationEnabled = true
return false
}
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
print("COORDINATE \(coordinate)") // when you tapped coordinate
}
func didTapMyLocationButton(for mapView: GMSMapView) -> Bool {
googleMaps.isMyLocationEnabled = true
googleMaps.selectedMarker = nil
return false
}
    
    //MARK: - Marker Delegate
    func mapView(_ mapView: GMSMapView, didDrag marker: GMSMarker) {
    
    
        }
    
    func mapView(_ mapView: GMSMapView, didBeginDragging marker: GMSMarker) {
        
        
    }
    
    func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) {
        self.googleMaps.reloadInputViews()

        //self.polyline.map = nil;
        print("marker dragged to location: \(marker.position.latitude),\(marker.position.longitude)")
       let locationMobi = CLLocation(latitude: marker.position.latitude, longitude: marker.position.longitude)
        self.drawPath(startLocation: locationMobi, endLocation: locationEnd)

    }


//MARK: - this is function for create direction path, from start location to desination location
func drawPath(startLocation: CLLocation, endLocation: CLLocation)
{
let origin = "\(startLocation.coordinate.latitude),\(startLocation.coordinate.longitude)"
let destination = "\(endLocation.coordinate.latitude),\(endLocation.coordinate.longitude)"
        self.polyline.map = nil
        //self.googleMaps.clear()

let url = "https://maps.googleapis.com/maps/api/directions/json?origin=\(origin)&destination=\(destination)&mode=driving"
Alamofire.request(url).responseJSON { response in
print(response.request as Any// original URL request
print(response.response as Any) // HTTP URL response
print(response.data as Any)     // server data
print(response.result as Any)   // result of response serialization
let json = JSON(data: response.data!)
let routes = json["routes"].arrayValue
// print route using Polyline
for route in routes
{
let routeOverviewPolyline = route["overview_polyline"].dictionary
let points = routeOverviewPolyline?["points"]?.stringValue
let path = GMSPath.init(fromEncodedPath: points!)
                self.polyline = GMSPolyline.init(path: path)
self.polyline.strokeWidth = 2
self.polyline.strokeColor = UIColor.red
self.polyline.map = self.googleMaps
}
}
}
// MARK: when start location tap, this will open the search location
@IBAction func openStartLocation(_ sender: UIButton) {
let autoCompleteController = GMSAutocompleteViewController()
autoCompleteController.delegate = self
// selected location
locationSelected = .startLocation
// Change text color
UISearchBar.appearance().setTextColor(color: UIColor.black)
self.locationManager.stopUpdatingLocation()
self.present(autoCompleteController, animated: true, completion: nil)
}
// MARK: when destination location tap, this will open the search location
@IBAction func openDestinationLocation(_ sender: UIButton) {
let autoCompleteController = GMSAutocompleteViewController()
autoCompleteController.delegate = self
// selected location
locationSelected = .destinationLocation
// Change text color
UISearchBar.appearance().setTextColor(color: UIColor.black)
self.locationManager.stopUpdatingLocation()
self.present(autoCompleteController, animated: true, completion: nil)
}
// MARK: SHOW DIRECTION WITH BUTTON
@IBAction func showDirection(_ sender: UIButton) {
// when button direction tapped, must call drawpath func
self.drawPath(startLocation: locationStart, endLocation: locationEnd)
}

}

// MARK: - GMS Auto Complete Delegate, for autocomplete search location
extension ViewController: GMSAutocompleteViewControllerDelegate {
func viewController(_ viewController: GMSAutocompleteViewController, didFailAutocompleteWithError error: Error) {
print("Error \(error)")
}
func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
// Change map location
let camera = GMSCameraPosition.camera(withLatitude: place.coordinate.latitude, longitude: place.coordinate.longitude, zoom: 16.0
)
// set coordinate to text
if locationSelected == .startLocation {
startLocation.text = "\(place.coordinate.latitude), \(place.coordinate.longitude)"
locationStart = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
createMarker(titleMarker: "Location Start", iconMarker: #imageLiteral(resourceName: "mapspin"), latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
} else {
destinationLocation.text = "\(place.coordinate.latitude), \(place.coordinate.longitude)"
locationEnd = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
createMarker(titleMarker: "Location End", iconMarker: #imageLiteral(resourceName: "mapspin"), latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
}
self.googleMaps.camera = camera
self.dismiss(animated: true, completion: nil)
}
func wasCancelled(_ viewController: GMSAutocompleteViewController) {
self.dismiss(animated: true, completion: nil)
}
func didRequestAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
func didUpdateAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}

public extension UISearchBar {
public func setTextColor(color: UIColor) {
let svs = subviews.flatMap { $0.subviews }
guard let tf = (svs.filter { $0 is UITextField }).first as? UITextField else { return }
tf.textColor = color
}

}

Comments

Post a Comment

Popular posts from this blog

Route between two places using Google Maps iOS SDK.

Its very interesting to have the Google maps  Firstly. We have to install the pods of Google maps. So, follow the steps for installing the pods of Google maps on developers.google.com 1. Create the pod file as on the site. 2. In Podfile add the pod of Alamofire and SwiftyJSON. 3. Save the pod file.      pod 'GoogleMaps'     pod 'GooglePlaces'     pod 'Alamofire' , '~> 4.2.0'     pod 'SwiftyJSON' 4. Install the pods. Here is the code for route. import UIKit import GoogleMaps import GooglePlaces import Alamofire import SwiftyJSON class GoogleViewController: UIViewController , GMSMapViewDelegate {     @IBOutlet weak var googleView: GMSMapView !          // AIzaSyC907BQBnrZK0UjA2zARtE6Mq7L__yqw5Q     override func viewDidLoad() {         super . viewDidLoad ()         GMSSe...

UIDatePicker Example with UIToolBar | iOS | Swift

UIDatePicker object use to select the date and time, The UIDatePicker class have multiple rotate wheels and take value from that wheel and give one object of UIDatePicker and to get date from UIDatePicker object. In this example, take one textFiled in which to open the datePicker using inputView. and adding toolbar in DatePicker. Add the UITextField Delegate and drag it to view controller also. Follow the below steps : Step 1 :   Adding one textFiled named  textField_Date in ViewController and give IBOutlet connection and delegate. also take one UIDatePicker variable. @IBOutlet weak var textField_Date: UITextField! var datePicker : UIDatePicker! Step 2 :  The function pickUpDate to create UIDatePicker with ToolBar.  func pickUpDate(_ textField : UITextField){ // DatePicker self.datePicker = UIDatePicker(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216)) self.datePicker.backgroundColor = UIColor.white ...