GMSMarker infoWindow not updating - ios

I'm using Google map and it's marker. For displaying information on the marker I'm using custom View to display it. But values are not updating once I init it.Below is my code for that.
func mapView(_ mapView: GMSMapView!, markerInfoWindow marker: GMSMarker) -> UIView? {
let location = CLLocation(latitude: marker.position.latitude, longitude: marker.position.longitude
var markerView : MarkerInfoView = Bundle.main.loadNibNamed("MarkerInfoView", owner: self, options: nil)![0] as! MarkerInfoView
let geoCoder = CLGeocoder()
geoCoder.reverseGeocodeLocation(location) { (placemarkers, error) in
if let placemarker = placemarkers?.last {
var strAddress = ""
if let str = placemarker.name {
strAddress += str
}
if let str = placemarker.subAdministrativeArea {
strAddress += ", " + str
}
print(strAddress)
markerView.deviceInfo.text = "HELLO TESTING"
print(markerView.deviceInfo.text!) // This is printing "HELLO TESTING", but not updating on marker
markerView.addressInfo.text = strAddress
}
}
if let str = marker.snippet {
markerView.deviceInfo.text = str.components(separatedBy: "|")[0]
//TODO: add time
markerView.dateInfo.text = str.components(separatedBy: "|")[1]
// markerView.addressInfo.text = ""
}
else {
markerView.deviceInfo.text = ""
markerView.dateInfo.text = ""
// markerView.addressInfo.text = ""
}
return markerView
}
Please guide me how to update values in infoWindow.

Try this code
// MARKER - GoogleMaps delegate
func mapView(_ mapView: GMSMapView, markerInfoContents marker: GMSMarker) -> UIView? {
print("title \(markerTitle)")
var infoView:UIView!
infoView = UIView()
infoView.frame = CGRect(x: 0, y: 0, width: 300, height: 75)
infoView.backgroundColor = .black
let orderIDLbl = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 75))
orderIDLbl.text = "markerTitle" //Your title here
orderIDLbl.font = UIFont.systemFont(ofSize: 15)
orderIDLbl.textAlignment = NSTextAlignment.center
orderIDLbl.numberOfLines = 0
orderIDLbl.textColor = .white
infoView.addSubview(orderIDLbl)
return infoView
}

Related

How to get different icons to show on Annotation View in Swift?

I am new to swift. I am creating an AR app with AR annotation View, where I have created a places object to show on Annotation AR view, but I can't get different icons to show based on locations in AR view. I only get one specific icon to all the places. Please have a look at my code to help me out with this issue. Thank you very much!
Here is my code:
import UIKit
import AVFoundation
protocol AnnotationViewDelegate {
func didTouch(annotationView: AnnotationView)
}
class AnnotationView: ARAnnotationView {
var titleLabel: UILabel?
var distanceLabel: UILabel?
var delegate: AnnotationViewDelegate?
var backgroundView: UIView?
var pinImage: UIImageView?
let pinoImage = ["bakeries", "banks", "barber", "bars", "beaches", "breweries", "cardealer", "carrepair", "church", "cinema",
"coffee", "college", "dentist", "dining", "doctors", "drycleaning", "fastfood", "firetruck", "fitness", "gas",
"grocery", "hospital", "hotel", "library", "lounges", "motorcycledealers", "musicvenues", "park", "petstore",
"pharmacy", "police", "postoffice", "train", "transportation", "zoo"]
override func didMoveToSuperview() {
super.didMoveToSuperview()
loadUI()
}
func getRandomColor() -> UIColor{
let red:CGFloat = CGFloat(drand48())
let green:CGFloat = CGFloat(drand48())
let blue:CGFloat = CGFloat(drand48())
return UIColor(red:red, green: green, blue: blue, alpha: 1.0)
}
func loadUI() {
titleLabel?.removeFromSuperview()
distanceLabel?.removeFromSuperview()
backgroundView?.removeFromSuperview()
pinImage?.removeFromSuperview()
backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: 70))
backgroundView?.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.5)
backgroundView?.layer.cornerRadius = 10.0
self.addSubview(backgroundView!)
pinImage = UIImageView(frame: CGRect(x: 16, y: 8, width: 37.76, height: 54))
pinImage?.contentMode = UIViewContentMode.scaleAspectFit
self.backgroundView?.addSubview(pinImage!)
let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: 22.0))
label.font = UIFont(name: "AvenirNext", size: 3)
label.numberOfLines = 0
label.textAlignment = .center
label.textColor = UIColor.white
self.backgroundView?.addSubview(label)
self.titleLabel = label
distanceLabel = UILabel(frame: CGRect(x: 66, y: 47, width: self.frame.size.width, height: 15.0))
distanceLabel?.textColor = UIColor.black
distanceLabel?.font = UIFont(name: "Montserrat-Regular", size: 12)
self.backgroundView?.addSubview(distanceLabel!)
if let annotation = annotation as? Place {
titleLabel?.text = annotation.placeName
distanceLabel?.text = String(format: "%.2f mi", annotation.distanceFromUser * 0.000621371)
pinImage?.image = UIImage(named: "FastFood")
}
}
override func layoutSubviews() {
super.layoutSubviews()
backgroundView?.frame = CGRect(x: 0, y: 0, width: 170, height: 80)
titleLabel?.frame = CGRect(x: 50, y: 8, width: self.frame.size.width - 66, height: 22.0)
distanceLabel?.frame = CGRect(x: 50, y: 30, width: self.frame.size.width, height: 20)
pinImage = UIImageView(frame: CGRect(x: 16, y: 8, width: 37.76, height: 54))
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
delegate?.didTouch(annotationView: self)
}
}
MapViewController
import UIKit
import MapKit
import CoreLocation
class MapViewController: BaseViewController, UITabBarDelegate{
#IBOutlet weak var leadingConstraints: NSLayoutConstraint!
#IBOutlet weak var mapView: MKMapView!
fileprivate let locationManager = CLLocationManager()
fileprivate var startedLoadingPOIs = false
fileprivate var places = [Place]()
fileprivate var arViewController: ARViewController!
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
var nearMeIndexSelected = NearMeIndexTitle()
var place: Place?
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
locationManager.requestWhenInUseAuthorization()
}
#IBAction func showARController(_ sender: Any) {
arViewController = ARViewController()
arViewController.dataSource = self
arViewController.maxVisibleAnnotations = 30
arViewController.headingSmoothingFactor = 0.05
arViewController.setAnnotations(places)
self.present(arViewController, animated: true, completion: nil)
}
}
extension MapViewController: CLLocationManagerDelegate, MKMapViewDelegate {
func mapView(_ mapView: MKMapView,
viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
mapView.tintColor = #colorLiteral(red: 0.08235294118, green: 0.7058823529, blue: 0.9450980392, alpha: 1)
return nil
} else {
let pin = mapView.view(for: annotation) ?? MKAnnotationView(annotation: annotation, reuseIdentifier: nil)
pin.image = UIImage(named: "pins")
return pin
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if locations.count > 0 {
let location = locations.last!
print("Accuracy: \(location.horizontalAccuracy)")
if location.horizontalAccuracy < 100 {
manager.stopUpdatingLocation()
let span = MKCoordinateSpan(latitudeDelta: 0.013, longitudeDelta: 0.013)
let region = MKCoordinateRegion(center: location.coordinate, span: span)
mapView.region = region
if !startedLoadingPOIs {
DispatchQueue.main.async {
self.activityIndicator.startAnimating()
}
startedLoadingPOIs = true
let loader = PlacesLoader()
loader.loadPOIS(location: location, radius: 1500) { placesDict, error in
if let dict = placesDict {
guard let placesArray = dict.object(forKey: "results") as? [NSDictionary] else { return }
for placeDict in placesArray {
let latitude = placeDict.value(forKeyPath: "geometry.location.lat") as! CLLocationDegrees
let longitude = placeDict.value(forKeyPath: "geometry.location.lng") as! CLLocationDegrees
let reference = placeDict.object(forKey: "reference") as! String
let name = placeDict.object(forKey: "name") as! String
let address = placeDict.object(forKey: "vicinity") as! String
let location = CLLocation(latitude: latitude, longitude: longitude)
let place = Place(location: location, reference: reference, name: name, address: address)
self.places.append(place)
let annotation = PlaceAnnotation(location: place.location!.coordinate, title: place.placeName)
DispatchQueue.main.async {
self.mapView.addAnnotation(annotation)
}
}
DispatchQueue.main.async {
self.activityIndicator.stopAnimating()
self.mapView.isHidden = false
}
}
}
}
}
}
}
}
extension MapViewController: ARDataSource {
func ar(_ arViewController: ARViewController, viewForAnnotation: ARAnnotation) -> ARAnnotationView {
let annotationView = AnnotationView()
arViewController.title = "MyApp"
annotationView.annotation = viewForAnnotation
annotationView.delegate = self
annotationView.frame = CGRect(x: 0, y: 0, width: 150, height: 50)
return annotationView
}
}
In Mapview class add the below code
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if (annotation is MKUserLocation) {
return nil
}
let reuseId = "reuseId"
let anView : AnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as! AnnotationView
if let annotation = annotation as? Place {
anView.titleLabel?.text = annotation.placeName
anView.distanceLabel?.text = String(format: "%.2f mi", annotation.distanceFromUser * 0.000621371)
if(annotation.placeName == "bakeries"){
anView.pinImage?.image = UIImage(named: "Bakery")
}
else{
anView.pinImage?.image = UIImage(named: "FastFood")
}
}
anView.canShowCallout = false
return anView
}
by the above the method you can change pin custom image

Add a label on MGLPolygon

I have a situation where I need to draw an MGLPolygon on a map(MapBox) and I also want to give a UILabel like text on the polygon. The label has to be at the centroid of the polygon and it should be always visible. I found a code with which I can find the centroid of a given polygon, But I couldn't add a label to polygon. I have done the coding in SWIFT so swift developers please help me. Thanks in advance and Happy Coding :)
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
if let currentAnnotation = annotation as? AreaAnnotation {
let reuseIdentifier = currentAnnotation.areaTitle
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier!)
if annotationView == nil {
annotationView = MGLAnnotationView(reuseIdentifier: reuseIdentifier)
annotationView?.frame = CGRect(x: 0, y: 0, width: 120, height: 90)
annotationView!.backgroundColor = UIColor.clear
let detailsLabel:UILabel = UILabel()
detailsLabel.frame = CGRect(x: 30, y: 60, width: 60, height: 25)
detailsLabel.textAlignment = .center
detailsLabel.text = currentAnnotation.areaTitle
// detailsLabel.textColor = UIColor(red:175/255 ,green:255/255, blue:255/255 , alpha:0.75)
detailsLabel.textColor = UIColor.white
detailsLabel.font = UIFont(name: "HelveticaNeue-CondensedBlack", size: 15)
let strokeTextAttributes = [NSAttributedStringKey.strokeColor : UIColor.black, NSAttributedStringKey.strokeWidth : -5.0,] as [NSAttributedStringKey : Any]
detailsLabel.attributedText = NSAttributedString(string: titleLabel.text!, attributes: strokeTextAttributes)
detailsLabel.backgroundColor = UIColor.black.withAlphaComponent(1.0)
detailsLabel.clipsToBounds = true
detailsLabel.layer.cornerRadius = 5.0
detailsLabel.layer.borderWidth = 2.0
detailsLabel.layer.borderColor = UIColor.white.cgColor
annotationView?.addSubview(detailsLabel)
}
return annotationView
}
return nil
}
Thanks #jmkiley but I wanted to clear out that issue as fast as possible so I used this tweak, which was the exact thing I wanted.
If you have the center point of the polygon, you could use it to create a MGLPointFeature. Then create a MGLShapeSource and MGLSymbolStyleLayer with it. Provide the text to that layer. For example:
import Mapbox
class ViewController: UIViewController, MGLMapViewDelegate {
var mapView : MGLMapView!
var line: MGLPolyline?
override func viewDidLoad() {
super.viewDidLoad()
mapView = MGLMapView(frame: view.bounds)
view.addSubview(mapView)
mapView.delegate = self
let coords = [
CLLocationCoordinate2D(latitude: 38.0654, longitude: -88.8135),
CLLocationCoordinate2D(latitude: 41.7549, longitude: -88.8135),
CLLocationCoordinate2D(latitude: 41.7549, longitude: -83.1226),
CLLocationCoordinate2D(latitude: 38.0654, longitude: -83.1226)
]
let polygon = MGLPolygon(coordinates: coords, count: UInt(coords.count))
mapView.addAnnotation(polygon)
}
func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) {
let point = MGLPointFeature()
point.coordinate = CLLocationCoordinate2D(latitude: 40.0781, longitude: -85.6714)
let source = MGLShapeSource(identifier: "point-source", features: [point], options: nil)
style.addSource(source)
let layer = MGLSymbolStyleLayer(identifier: "point-layer", source: source)
layer.text = MGLStyleValue(rawValue: "Polygon A")
style.addLayer(layer)
}
}

Display array of text in annotationView using index

I can't display all the addresses in my variable
var allAddress: [Address] = []
In this variable i get from firebase a small amount of addresses and i want to display all addresses in my annotationView, but when i try to display all addresses i see only one address in all annotationView though if i make printed my using for..in.. index i see index0, index1, index2, index3 and other... as well if i printed this:
print("address - \(allAddress[index].address)")
i get all address which i have in firebase, their total 6.
It's print my index and allAddress[index].address
index 1
address - Москва, ул. Правды д.24, строение 3
index 2
address - Москва, ул.Электрозаводская д.21
index 3
address - Москва, ул.Бутырская д.8
index 4
address - Москва, 2-Я Звенигородская улица 12 строение 21
index 5
address - Москва, Николоямская 52, стр. 1
It's my code:
let centerInfo = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 100))
for index in 0..<allAddress.count {
print("index \(index)")
centerInfo.text = allAddress[index].address
centerInfo.numberOfLines = 0
centerInfo.lineBreakMode = .byWordWrapping
print("address - \(allAddress[index].address)")
}
annotationView?.detailCalloutAccessoryView = centerInfo
How i can display all addresses in my centerInfo.text?
And pls check .gif which shows the same address on all annotationView
P.S. in annotation.title don't need to use, me do not fit
UPDATED. All code:
class AllAddressMapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
var allAddress: [Address] = []
var studioRef: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
studioRef = Database.database().reference(withPath: "Photo1")
studioRef.observe(.value, with: { (snapshot) in
for imageSnap in snapshot.children {
let studioObj = Studio(snapshot: imageSnap as! DataSnapshot)
self.allAddress.append(studioObj)
for index in 0..<self.allAddress.count {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(self.allAddress[index].address, completionHandler: { (placemarks, error) in
guard error == nil else { return }
guard let placemarks = placemarks else { return }
if let placemark = placemarks.first {
let annotation = MKPointAnnotation()
guard let address = placemark.location else { return }
annotation.coordinate = address.coordinate
self.mapView.addAnnotation(annotation)
}
geocoder.cancelGeocode()
})
}
}
})
mapView.delegate = self
mapView.mapType = .standard
mapView.isZoomEnabled = true
mapView.isScrollEnabled = true
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard !(annotation is MKUserLocation) else { return nil }
let annotationID = "PinMap"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationID) as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: annotationID)
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
let leftImageNavigationButton = UIImage(named: "auto")
let tintedColorleftImageNavigationButton = leftImageNavigationButton?.withRenderingMode(.alwaysTemplate)
let leftNavigationButton = UIButton(type: .custom)
leftNavigationButton.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
leftNavigationButton.setImage(tintedColorleftImageNavigationButton, for: UIControlState())
leftNavigationButton.tintColor = #colorLiteral(red: 0, green: 0.4784313725, blue: 1, alpha: 1)
annotationView?.leftCalloutAccessoryView = leftNavigationButton
let rightButtonInfo = UIButton(type: .detailDisclosure)
annotationView?.rightCalloutAccessoryView = rightButtonInfo
let centerInfo = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 100))
for index in 0..<allAddress.count {
print("index \(index)")
centerInfo.text = allAddress[index].address
centerInfo.numberOfLines = 0
centerInfo.lineBreakMode = .byWordWrapping
print("address - \(allAddress[index].address)")
}
annotationView?.detailCalloutAccessoryView = centerInfo
annotationView?.calloutOffset = CGPoint(x: -8, y: 0)
return annotationView
}
}
From your code, it looks , you are using same UILabel for all annotation and in loop you are setting the text property of the same UILabel every time. That's why it's showing the last address on all annotation.
Try to assign a separate UILabel for each annotation and set text property to the designated address
Well, the idea is to get all annotations on your map like that and try to find the right annotation index to reuse it into your allAddress array :
var indexValue = 0
for annotationInMap in mapView.annotations {
if annotation == annotationInMap {
let centerInfo = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 100))
centerInfo.text = allAddress[indexValue].address
centerInfo.numberOfLines = 0
centerInfo.lineBreakMode = .byWordWrapping
annotationView?.detailCalloutAccessoryView = centerInfo
}
indexValue = indexValue + 1
}
How about setting address to annotation.title in viewDidLoad, and get annotation.title in viewFor method.
class AllAddressMapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
var allAddress: [Address] = []
var studioRef: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
studioRef = Database.database().reference(withPath: "Photo1")
studioRef.observe(.value, with: { (snapshot) in
for imageSnap in snapshot.children {
let studioObj = Studio(snapshot: imageSnap as! DataSnapshot)
self.allAddress.append(studioObj)
for index in 0..<self.allAddress.count {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(self.allAddress[index].address, completionHandler: { (placemarks, error) in
guard error == nil else { return }
guard let placemarks = placemarks else { return }
if let placemark = placemarks.first {
let annotation = MKPointAnnotation()
guard let address = placemark.location else { return }
annotation.coordinate = address.coordinate
annotation.title = self.allAddress[index].address
self.mapView.addAnnotation(annotation)
}
geocoder.cancelGeocode()
})
}
}
})
mapView.delegate = self
mapView.mapType = .standard
mapView.isZoomEnabled = true
mapView.isScrollEnabled = true
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard !(annotation is MKUserLocation) else { return nil }
let annotationID = "PinMap"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationID) as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: annotationID)
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
let leftImageNavigationButton = UIImage(named: "auto")
let tintedColorleftImageNavigationButton = leftImageNavigationButton?.withRenderingMode(.alwaysTemplate)
let leftNavigationButton = UIButton(type: .custom)
leftNavigationButton.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
leftNavigationButton.setImage(tintedColorleftImageNavigationButton, for: UIControlState())
leftNavigationButton.tintColor = #colorLiteral(red: 0, green: 0.4784313725, blue: 1, alpha: 1)
annotationView?.leftCalloutAccessoryView = leftNavigationButton
let rightButtonInfo = UIButton(type: .detailDisclosure)
annotationView?.rightCalloutAccessoryView = rightButtonInfo
let centerInfo = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 100))
for index in 0..<allAddress.count {
print("index \(index)")
centerInfo.text = annotation.title
centerInfo.numberOfLines = 0
centerInfo.lineBreakMode = .byWordWrapping
print("address - \(allAddress[index].address)")
}
annotationView?.detailCalloutAccessoryView = centerInfo
annotationView?.calloutOffset = CGPoint(x: -8, y: 0)
return annotationView
}

Google place autocomplete in swift doesn't works perfectly

I tried to make "place autocomplete" from google place and I copy paste the codes directly from the website here google developer and I already set the api key too but the problem is why the results look so odd when I typing a place as you can see on the picture it seems works but not perfect. here is my code:
import UIKit
import GoogleMaps
class FetcherSampleViewController: UIViewController {
var textField: UITextField?
var resultText: UITextView?
var fetcher: GMSAutocompleteFetcher?
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.whiteColor()
self.edgesForExtendedLayout = .None
// Set bounds to inner-west Sydney Australia.
let neBoundsCorner = CLLocationCoordinate2D(latitude: -33.843366,
longitude: 151.134002)
let swBoundsCorner = CLLocationCoordinate2D(latitude: -33.875725,
longitude: 151.200349)
let bounds = GMSCoordinateBounds(coordinate: neBoundsCorner,
coordinate: swBoundsCorner)
// Set up the autocomplete filter.
let filter = GMSAutocompleteFilter()
filter.type = .Establishment
// Create the fetcher.
fetcher = GMSAutocompleteFetcher(bounds: bounds, filter: filter)
fetcher?.delegate = self
textField = UITextField(frame: CGRect(x: 5.0, y: 0,
width: self.view.bounds.size.width - 5.0, height: 44.0))
textField?.autoresizingMask = .FlexibleWidth
textField?.addTarget(self, action: "textFieldDidChange:",
forControlEvents: .EditingChanged)
resultText = UITextView(frame: CGRect(x: 0, y: 45.0,
width: self.view.bounds.size.width,
height: self.view.bounds.size.height - 45.0))
resultText?.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
resultText?.text = "No Results"
resultText?.editable = false
self.view.addSubview(textField!)
self.view.addSubview(resultText!)
}
func textFieldDidChange(textField: UITextField) {
fetcher?.sourceTextHasChanged(textField.text!)
}
}
extension FetcherSampleViewController: GMSAutocompleteFetcherDelegate {
func didAutocompleteWithPredictions(predictions: [GMSAutocompletePrediction]) {
let resultsStr = NSMutableString()
for prediction in predictions {
resultsStr.appendFormat("%#\n", prediction.attributedPrimaryText)
}
resultText?.text = resultsStr as String
}
func didFailAutocompleteWithError(error: NSError) {
resultText?.text = error.localizedDescription
}
}
can anyone help me?
This is because prediction.attributedPrimaryText is an attributed string. Try the following code
func didAutocompleteWithPredictions(predictions: [GMSAutocompletePrediction]) {
let resultsStr = NSMutableAttributedString()
for prediction in predictions {
resultsStr.appendAttributedString(prediction.attributedPrimaryText)
resultsStr.appendAttributedString(NSAttributedString(string: "\n"))
}
resultText?.attributedText = resultsStr
}

How to do animation in custom annotation pin when update annotation view

I want to do animation like "when scroll collection view cell the annotation pin goes Up/Down at the end of scrolling. But how to do animation like annotation pin goes Up when start scrolling and annotation pin goes Down when scrolling end in collection view
//code --> For Scrolling
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
if scrollView == collectionView {
NSLog("page collection %d",Int(scrollView.contentOffset.x/scrollView.frame.size.width))
self.UpdateMapAnotationPin(Int(scrollView.contentOffset.x/scrollView.frame.size.width))
}
}
// -->When Update Pin
func UpdateMapAnotationPin(vIndex : Int) {
if self.mapAnnotations.count != 0 {
let info = self.mapAnnotations[vIndex]
let aView = map.viewForAnnotation(info)
info.imageName = "ic_map_pin1"
info.tagPin = vIndex
aView?.image = UIImage(named: info.imageName)
if aView != nil {
self.animationWithView(aView!)
}
}
}
// --> For animation
func animationWithView(mkView : MKAnnotationView) {
let point:MKMapPoint = MKMapPointForCoordinate(mkView.annotation!.coordinate);
let endFrame:CGRect = mkView.frame;
mkView.frame = CGRectMake(mkView.frame.origin.x, mkView.frame.origin.y - 20, mkView.frame.size.width, mkView.frame.size.height);
let delay = 0.03
UIView.animateWithDuration(0.5, delay: delay, options: UIViewAnimationOptions.CurveLinear, animations:{() in
mkView.frame = endFrame
}, completion:{(Bool) in
UIView.animateWithDuration(0.05, delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations:{() in
mkView.transform = CGAffineTransformMakeScale(1.0, 1.0) }, completion: {(Bool) in
UIView.animateWithDuration(0.3, delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations:{() in
mkView.transform = CGAffineTransformIdentity
}, completion: nil)
})
})
}
I think you want to animated like AirBnb app annotations.
You have to select the pin by calling it's viewforAnimation method
Steps
1.Make annotation using by assigning the custom id like this
class GridAnnotation: NSObject ,MKAnnotation{
var title: String?
var coordinate: CLLocationCoordinate2D
var info: String
var index: String
init(title: String, coordinate: CLLocationCoordinate2D, info: String,index: String) {
self.title = title
self.coordinate = coordinate
self.info = info
self.index = index
}
}
override func viewDidLoad() {
super.viewDidLoad()
let annotationStart = GridAnnotationStart(title: "", coordinate: firstLocation.coordinate, info: "\(zoneCreateModal.id)",index: "\(0)")
self.mapVw.addAnnotation(annotationSta
rt)
}
2.Get all annotations
let arrAllAnnotations = self.mapVw.annotations.filter { $0 !== self.mapVw.userLocation }
for someAnnotation in annotationsToRemove {
let strId = "Your current id"
if someAnnotation.isKind(of: AnnotationModal.self) {
let annotaion = someAnnotation as! AnnotationModal
if annotaion.info == strId {
//Call view for animation
self.mapVw.selectAnnotation(someAnnotation, animated: true)
self.mapVw.view(for: someAnnotation)
}
}
}
5.Set type of new selected annoatation in viewForAnnotation
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if (annotation.isKind(of: MKUserLocation.self)) {
return nil
}
if annotation.isKind(of: GridAnnotationZoomModal.self) {
let anView = MKAnnotationView(annotation: annotation, reuseIdentifier: "landingPoints")
let annotationInfo = annotation as! GridAnnotationZoomModal
imgView.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
if anView.isSelected == true {
imgView.image = UIImage(named: "Your selected image name")
}else{
imgView.image = UIImage(named: "Your image not selected name")
}
anView.isDraggable = false
anView.isEnabled = true
anView.isUserInteractionEnabled = true
anView.tag = Int(annotationInfo.index)!
anView.addSubview(imgView)
anView.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
anView.centerOffset = CGPoint(x: 0,y: -15)
return anView
}
return nil
}

Resources