Last active
July 20, 2022 14:47
-
-
Save tadeha/0d7df23394c3310fbfa6da4b9efc4360 to your computer and use it in GitHub Desktop.
🗺Map View with Bottom Components for each Marker // Using Google Maps and written in Swift 5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MapViewController.swift | |
// | |
// Created by Tadeh Alexani on 7/14/19. | |
// Copyright © 2019 Tadeh Alexani. All rights reserved. | |
// | |
import UIKit | |
import GoogleMaps | |
class MapViewController: UIViewController { | |
@IBOutlet weak var mapView: GMSMapView! | |
@IBOutlet weak var collectionView: UICollectionView! | |
var locationManager = CLLocationManager() | |
var zoomLevel: Float = 15.0 | |
var restaurants = [Restaurant]() | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
// Initialize the location manager. | |
locationManager = CLLocationManager() | |
locationManager.desiredAccuracy = kCLLocationAccuracyBest | |
locationManager.distanceFilter = 50 | |
locationManager.startUpdatingLocation() | |
locationManager.delegate = self | |
mapView.delegate = self | |
//mapView.settings.myLocationButton = true | |
mapView.isMyLocationEnabled = true | |
mapView.isHidden = true | |
// If the value of this property is true, the scroll view stops on multiples of the scroll view’s bounds when the user scrolls. | |
collectionView.isPagingEnabled = true | |
} | |
} | |
// Delegates to handle events for the location manager. | |
extension MapViewController: CLLocationManagerDelegate { | |
// Handle incoming location events. | |
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { | |
let location: CLLocation = locations.last! | |
// Define getList Function in your class to fill your sample array (here restaurants) and then don't forget to RELOAD COLLECTION VIEW | |
getListOfRestaurants(with: location) | |
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude, | |
longitude: location.coordinate.longitude, | |
zoom: zoomLevel) | |
if mapView.isHidden { | |
mapView.isHidden = false | |
mapView.camera = camera | |
} else { | |
mapView.animate(to: camera) | |
} | |
} | |
// Handle authorization for the location manager. | |
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { | |
switch status { | |
case .restricted: | |
print("Location access was restricted.") | |
case .denied: | |
print("User denied access to location.") | |
// Display the map using the default location. | |
mapView.isHidden = false | |
case .notDetermined: | |
print("Location status not determined.") | |
case .authorizedAlways: fallthrough | |
case .authorizedWhenInUse: | |
print("Location status is OK.") | |
@unknown default: | |
fatalError() | |
} | |
} | |
// Handle location manager errors. | |
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { | |
locationManager.stopUpdatingLocation() | |
print("Error: \(error)") | |
} | |
} | |
extension MapViewController: UICollectionViewDelegate, UICollectionViewDataSource { | |
func collectionView(_ collectionView: UICollectionView, | |
numberOfItemsInSection section: Int) -> Int { | |
return restaurants.count | |
} | |
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { | |
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mapDetailCell", | |
for: indexPath) as? MapRestaurantDetailCollectionViewCell else { | |
fatalError("The dequeued cell is not an instance of mapDetailCell.") | |
} | |
let restaurant = restaurants[indexPath.row] | |
cell.nameLabel.text = restaurant.name | |
cell.addressLabel.text = restaurant.address | |
ImageHelper.shared.loadImage(withUrl: restaurant.logo, imgView: cell.logoImgView) | |
// Add location marker on the map | |
let marker = GMSMarker(position: CLLocationCoordinate2D(latitude: restaurant.lat, longitude: restaurant.long)) | |
marker.userData = ["slug": restaurant.slug, "indexPath": indexPath] | |
marker.icon = ImageHelper.shared.imageWithImage(image: UIImage(named: "detail-pin-icon")!, scaledToSize: CGSize(width: 22, height: 31)) | |
marker.map = self.mapView | |
return cell | |
} | |
// Handle when user scrolls the horizontal collection view (here change the map camera position to the selected restaurant marker) | |
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { | |
var visibleRect = CGRect() | |
visibleRect.origin = collectionView.contentOffset | |
visibleRect.size = collectionView.bounds.size | |
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY) | |
guard let indexPath = collectionView.indexPathForItem(at: visiblePoint) else { return } | |
let restaurant = restaurants[indexPath.row] | |
let camera = GMSCameraPosition.camera(withLatitude: restaurant.lat, | |
longitude: restaurant.long, | |
zoom: zoomLevel) | |
mapView.animate(to: camera) | |
} | |
} | |
extension MapViewController: GMSMapViewDelegate { | |
// Handle when user tapped on a marker (here scroll to the selected item on the collection view) | |
@objc(mapView:didTapMarker:) func mapView(_: GMSMapView, didTap marker: GMSMarker) -> Bool { | |
guard let userData = marker.userData as? [String:Any] else { return false } | |
guard let indexPath = userData["indexPath"] as? IndexPath else { return false } | |
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .right) | |
return true | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Great.👌