Use any custom view as custom callout view for MKMapView with cool animations. Use any image as annotation view.

Overview

MapViewPlus

Swift 5.0 iOS 10.0+ Version License Platform

About

MapViewPlus gives you the missing methods of MapKit which are: imageForAnnotation and calloutViewForAnnotationView delegate methods.

  • Return any UIImage from imageForAnnotation (image shouldn't have paddings)
  • Create any UIView to use as your custom callout view and return it from calloutViewForAnnotationView
  • MapViewPlus will:
    1. Add an anchor view to bottom of your callout view
    2. Combine callout view with the anchor view and add shadow to both of them
    3. Add a cool animation to CalloutAndAnchorView
    4. Make it user interaction enabled (this may be easy but tricky sometimes)
    5. Scrolls map view to show the callout view completely after tapping the annotation view
    6. Even give a ready-to-use template for callout view
    7. Forward all of the delegate methods of MKMapView to your subclass of MapViewPlus (except mapView:viewForAnnotation:)

Requirements

  • Swift 5.0
  • iOS 10.0+

Installation

MapViewPlus is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'MapViewPlus'

If you don't use CocoaPods, you can drag and drop all the classes and use it in your project.

How to use

1) If you are using Interface Builder, set your map view's class and module as MapViewPlus:

2) Setup your Callout View Model:

import UIKit
import MapViewPlus

// CalloutViewModel is a protocol of MapVieWPlus. Currently, it has no requirements to its conformant classes.
class YourCalloutViewModel: CalloutViewModel {

  var title: String
  var image: UIImage

  init(title: String, image: UIImage) {
    self.title = title
    self.image = image
  }
}

3) Setup your CalloutView:

  • Create any view in an xib file (or programmatically):

  • Wire your view to your callout view class:
import UIKit
import MapViewPlus

// CalloutViewPlus is a protocol of MapViewPlus. 
// Currently, it has just one requirement -> func configureCallout(_ viewModel: CalloutViewModel)
class YourCalloutView: UIView, CalloutViewPlus {

  @IBOutlet weak var label: UILabel!
  @IBOutlet weak var imageView: UIImageView!

  func configureCallout(_ viewModel: CalloutViewModel) {
    let viewModel = viewModel as! YourCalloutViewModel

    label.text = viewModel.title
    imageView.image = viewModel.image
  }
}

4) Setup your Annotations in your View Controller:

import UIKit
import CoreLocation
import MapViewPlus

class YourViewController: UIViewController {

  @IBOutlet weak var mapView: MapViewPlus!

  override func viewDidLoad() {
    super.viewDidLoad()

    //Required
    mapView.delegate = self

    let viewModel = YourCalloutViewModel(title: "Cafe", image: UIImage(named: "cafe.png")!)

    let annotation = AnnotationPlus(viewModel: viewModel,
                                    coordinate: CLLocationCoordinate2DMake(50.11, 8.68))

    var annotations: [AnnotationPlus] = []
    annotations.append(annotation)

    mapView.setup(withAnnotations: annotations)
  }
}

5) Return the image for Annotation and the View for Callout

extension YourViewController: MapViewPlusDelegate {

  func mapView(_ mapView: MapViewPlus, imageFor annotation: AnnotationPlus) -> UIImage {
    return UIImage(named: "your_annotation_image.png")!
  }

  func mapView(_ mapView: MapViewPlus, calloutViewFor annotationView: AnnotationViewPlus) -> CalloutViewPlus{
    let calloutView = Bundle.main.loadNibNamed("YourCalloutView", owner: nil, options: nil)!.first as! YourCalloutView
    return calloutView
  }
}

This is it. You are all set and ready to go now.

Customization (Optional)

MapViewPlus is highly customizable:

CalloutViewCustomizerDelegate

  • Change the center of the callout view related to anchor view and callout view:
func mapView(_ mapView: MapViewPlus, centerForCalloutViewOf annotationView: AnnotationViewPlus) -> CalloutViewPlusCenter
  • Change the bounds for callout view without changing the frames in Interface Builder. If you don't use this delegate method, then your callout view's frame will stay the same as the Interface Builder file. You can also use this to change frame dynamically according to the data in callout view!
func mapView(_ mapView: MapViewPlus, boundsForCalloutViewOf annotationView: AnnotationViewPlus) -> CalloutViewPlusBound
  • Change the inset of anchor view related to callout view. Anchor view will go under the callout view as amount the value you returned from this method. Defaults to 0.
func mapView(_ mapView: MapViewPlus, insetFor calloutView: CalloutViewPlus) -> CGFloat
  • Change the animation type for showing the callout view. Defaults to .fromBottom and available types are, .fromTop, .fromBottom, .fromLeft, .fromRight
func mapView(_ mapView: MapViewPlus, animationTypeForShowingCalloutViewOf annotationView: AnnotationViewPlus) -> CalloutViewShowingAnimationType
  • Change the animation type for hiding the callout view. Defaults to .toBottom and available types are, .toTop, .toBottom, .toLeft, .toRight
func mapView(_ mapView: MapViewPlus, animationTypeForHidingCalloutViewOf annoationView: AnnotationViewPlus) -> CalloutViewHidingAnimationType

AnchorViewCustomizerDelegate

  • Change the height for anchor. Anchor view will always draw a equilateral triangle by taking the value you supplied as the triangle's height. You can change the height and the anchor view will calculate the necessary size for you:
func mapView(_ mapView: MapViewPlus, heightForAnchorOf calloutView: CalloutViewPlus) -> CGFloat
  • Change the background color of anchor view. This is very important. You can supply any color you want for the anchor view. Generally you would like to make this color as same as the background color of your callout view. Just change it like:
func mapView(_ mapView: MapViewPlus, fillColorForAnchorOf calloutView: CalloutViewPlus) -> UIColor

Notes

DefaultCalloutView

  • MapViewPlus supplies you a ready-to-go template for callout view. You can see the usage example of it in the example project.
  • It allows you to specify the source of the image. It has three options:
    1. .downloadable(imageURL: URL, placeholder: UIImage?)
      • Downloads the image with the help of Kingfisher framework
    2. .fromBundle(image: UIImage)
    3. .none

Forwarding Delegate Methods

MapViewPlus uses methods from MKMapViewDelegate, but not all of them. It forwards all of the delegate methods except mapView:viewForAnnotation:. This method is used internally and won't be redirected to your subclass.

Normally, MapViewPlus will abstract you from MapKit when you don't want to use the other methods of MKMapViewDelegate. But when you want to use the other methods from MKMapViewDelegate, you can easily do that without any extra efforts. Just write them down and they will get called by MapViewPlusDelegate. Please see how mapView(_:regionDidChangeAnimated:) method is being called in DefaultCalloutViewController.swift (in the example project) even if you don't conform to MKMapViewDelegate. If in the future, some new methods are added to MKMapViewDelegate, they will be automagically forwarded to you by MapViewPlusDelegate without a new version of the framework. There is no wrapping occuring in the background.

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Screenshots

License

MapViewPlus is available under the MIT license. See the LICENSE file for more info.

Comments
  • How to properly set the Custom position for CalloutView?

    How to properly set the Custom position for CalloutView?

    func mapView(_ mapView: MapViewPlus, centerForCalloutViewOf annotationView: AnnotationViewPlus) -> CalloutViewPlusCenter {
            return .customCenter(self.mapViewPlus.center)
        }
    

    With the current code, it's not working. Even I tried with other values too but it's not working.

    opened by hemangshah 12
  • not working with Xcode 11

    not working with Xcode 11

    Im getting errors a bunch of errors when I run this on Xcode 11 specifically in the KIngFisher Pod attached to it where it shows that I have 11 errors in its files

    opened by xthemadgenius 3
  • unable to compile example

    unable to compile example

    Hi,

    Thanks for your example. I have been unable to compile, and receive following error:

    Showing Recent Messages :-1: Multiple commands produce '/Users/brian/Library/Developer/Xcode/DerivedData/MapViewPlus-cqabsqclifgkyqgnhukrshycpcez/Build/Products/Debug-iphoneos/MapViewPlus/MapViewPlus.framework/.gitkeep':

    1. Target 'MapViewPlus' (project 'Pods') has copy command from '/Users/brian/Documents/MapViewPlus/MapViewPlus/Assets/.gitkeep' to '/Users/brian/Library/Developer/Xcode/DerivedData/MapViewPlus-cqabsqclifgkyqgnhukrshycpcez/Build/Products/Debug-iphoneos/MapViewPlus/MapViewPlus.framework/.gitkeep'
    2. Target 'MapViewPlus' (project 'Pods') has copy command from '/Users/brian/Documents/MapViewPlus/MapViewPlus/Classes/.gitkeep' to '/Users/brian/Library/Developer/Xcode/DerivedData/MapViewPlus-cqabsqclifgkyqgnhukrshycpcez/Build/Products/Debug-iphoneos/MapViewPlus/MapViewPlus.framework/.gitkeep'

    I attempted to reinstall the Pod, compile the example. Tried removing derived data.

    What is the process to clone the project and compile?

    THanks, Brian

    opened by appsird 2
  • How to remove that triangle below the CalloutView?

    How to remove that triangle below the CalloutView?

    extension KiosksViewController: AnchorViewCustomizerDelegate {
        func mapView(_ mapView: MapViewPlus, fillColorForAnchorOf calloutView: CalloutViewPlus) -> UIColor {
            return UIColor.black.withAlphaComponent(0.0)
        }
    }
    

    Doing this showing a full black triangle. I can set the various colors but can't set the clear color.

    How to hide it completely?

    opened by hemangshah 2
  • How to change map view region in MapViewPlus?

    How to change map view region in MapViewPlus?

    i am try to change map view region in MapViewPlus but it will change map view region after add annotations

    How do i change map view region in MapViewPlus?

    opened by c1800054work 1
  • How can I get model On tap of Callout view?

    How can I get model On tap of Callout view?

    When we open on annotation, It opens callout. I want to get tap event on callout and also the model data of that callout. How can I get this?

    Any methods?

    opened by hadwanihardik 1
  • How to get the selected annotation?

    How to get the selected annotation?

    extension KiosksViewController: MapViewPlusDelegate {
        func mapView(_ mapView: MapViewPlus, calloutViewFor annotationView: AnnotationViewPlus) -> CalloutViewPlus {
            return EmptyView()
        }
    }
    

    As per my need, I don't want to show a CalloutView instead I will show up a View which I will add and display on self.view. So when I tap on any of the annotations, how would I get to know which annotation is tapped so that in my view I can update the label values from the selected annotation.

    opened by hemangshah 1
  • Not build with xcode 10

    Not build with xcode 10

    Showing Recent Issues :-1: Multiple commands produce '//Library/Developer/Xcode/DerivedData/MapViewPlus-emdjhzofperwsjdbtehiecufpaoa/Build/Products/Debug-iphonesimulator/MapViewPlus/MapViewPlus.framework/.gitkeep':

    1. Target 'MapViewPlus' (project 'Pods') has copy command from '//Downloads/MapViewPlus-master/MapViewPlus/Assets/.gitkeep' to '//Library/Developer/Xcode/DerivedData/MapViewPlus-emdjhzofperwsjdbtehiecufpaoa/Build/Products/Debug-iphonesimulator/MapViewPlus/MapViewPlus.framework/.gitkeep'
    2. Target 'MapViewPlus' (project 'Pods') has copy command from '//Downloads/MapViewPlus-master/MapViewPlus/Classes/.gitkeep' to '//Library/Developer/Xcode/DerivedData/MapViewPlus-emdjhzofperwsjdbtehiecufpaoa/Build/Products/Debug-iphonesimulator/MapViewPlus/MapViewPlus.framework/.gitkeep'
    opened by codaman 0
  • Add way to diff AnnotationViewPlus type

    Add way to diff AnnotationViewPlus type

    I don't really know how to check the type of my pin annotation type in delegate mapView(_ mapView: MapViewPlus, calloutViewFor annotationView: AnnotationViewPlus) -> CalloutViewPlus. The AnnotationViewPlus comes from nowhere, now define CalloutViewPlus is mandatory. What if I only want one pin to show callout view but not others? Having that hacking method to hide callout view for certain pins(as another issue thread mentioned) is kind of silly. Why don't you change this delegate return value as optional? I cannot show other subclass of MKAnnotation if I use only MapViewPlus, it just crashes as the mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? is overriden by MapViewPlus's delegate

    opened by ininex 0
  • Lib doesn't allow to add any other custom views to map

    Lib doesn't allow to add any other custom views to map

    https://github.com/okhanokbay/MapViewPlus/blob/72a7f331e42d539eef0b3b40016e2f8400d495e4/MapViewPlus/Classes/Source/MapViewPlus.swift

    guard subview is CalloutAndAnchorView else { return }
    

    You should replace return with continue otherwise it sometimes doesn't deselect the annotation views if sees any other type of subviews.

    P.S. Decided to rewrite your library because 50% of it meet our customer requirements only. Starting with removing of protocols with extra obligated methods.

    opened by gerchicov-bp 0
  • Adding custom annotation with text

    Adding custom annotation with text

    Hi,

    I have a requirement to add custom location marker with text of user name as short. Could you please help me to do this as this library is really helpful.

    Thanks, Hema

    enhancement 
    opened by hemaks777 3
  • Annotation place and touch problem

    Annotation place and touch problem

    When annotation is near the edges, calloutView half of part shows out of map

    and another problem, when tapping the button on calloutView, annotation under view is clicked

    enhancement 
    opened by codaman 5
  • How to stop showing CalloutView on annotation selection?

    How to stop showing CalloutView on annotation selection?

    I have a scenario for which I don't want to show a CalloutView to be displayed when an annotation will get selected. Instead, I want MapViewPlus to let me know that an annotation has been tapped and I will then show a custom popup on self.view. Is it possible with MapViewPlus?

    P.S. I understand that this is not the actual behavior of a MapView itself, however for someways is this will be possible it will be more easy for us to display a map with MapViewPlus while customizing the UI as per our need.

    enhancement 
    opened by hemangshah 4
Releases(0.1.2)
  • 0.1.2(Mar 29, 2018)

  • 0.1.1(Mar 13, 2018)

Owner
Okhan Okbay
Okhan Okbay
MKMapView wrapper for SwiftUI as drop-in to MapKit's SwiftUI view

MKMapView wrapper for SwiftUI as drop-in to MapKit's SwiftUI view. Easily extensible annotations and overlays, iOS 13 support and backwards compatible with MKAnnotation and MKOverlay!

Paul 73 Dec 26, 2022
360° flyover on a MKMapView 🚁

FlyoverKit enables you to present stunning 360° flyover views on an MKMapView with zero effort while maintaining full configuration possibilities. Fly

Sven Tiigi 693 Jan 3, 2023
Allows you to use custom maps in iphone applications and attempts to mimics some of the behaviour of the MapKit framework

NAMapKit Lets you drop pins or custom annotations onto a standard UIImage or a tiled NATiledImageView. Includes callouts, multi-colored pins, animatio

Neil Ang 263 Jun 29, 2022
Use Swift in the macOS command line to build maps.

Use Swift in the macOS command line to build maps. imagefrom A Swift command line utility that gets an image from a URL. Saves the web image as JPEG o

Rob Labs 0 Dec 30, 2021
Easy Map Annotation Clustering 📍

Cluster is an easy map annotation clustering library. This repository uses an efficient method (QuadTree) to aggregate pins into a cluster. Features R

Lasha Efremidze 1.2k Dec 25, 2022
Annotation - Generate files to train with Object Detection by Create ML

CreateML Annotation Generate files to train with Object Detection by Create ML.

Vaida 10 Nov 7, 2022
A Swift library to take the power of UIView.animateWithDuration(_:, animations:...) to a whole new level - layers, springs, chain-able animations and mixing view and layer animations together!

ver 2.0 NB! Breaking changes in 2.0 - due to a lot of requests EasyAnimation does NOT automatically install itself when imported. You need to enable i

Marin Todorov 3k Dec 27, 2022
MKMapView wrapper for SwiftUI as drop-in to MapKit's SwiftUI view

MKMapView wrapper for SwiftUI as drop-in to MapKit's SwiftUI view. Easily extensible annotations and overlays, iOS 13 support and backwards compatible with MKAnnotation and MKOverlay!

Paul 73 Dec 26, 2022
Single selection menu with cool animations

EEJSelectMenu EEJSelectMenu is a responsive single selection menu for iOS. Project allows for implementing a menu with different number of buttons and

Ehsan Jahromi 23 Sep 24, 2022
A simpler way to do cool UITableView animations! (╯°□°)╯︵ ┻━┻

TableFlip (╯°□°)╯︵ ┻━┻ ┬──┬ ノ( ゜-゜ノ) Animations are cool. UITableView isn't. So why not make animating UITableView cool? The entire API for TableFlip

Joe Fabisevich 555 Dec 9, 2022
360° flyover on a MKMapView 🚁

FlyoverKit enables you to present stunning 360° flyover views on an MKMapView with zero effort while maintaining full configuration possibilities. Fly

Sven Tiigi 693 Jan 3, 2023
Request the Location Services via a 3D 360° flyover MKMapView 🗺

STLocationRequest STLocationRequest is a simple and elegant way to request the users location services at the very first time. The STLocationRequestCo

Sven Tiigi 640 Dec 6, 2022
SwiftUI wrapper for MapKit's MKMapView (UIKit).

SwiftUIMKMapView SwiftUI wrapper for MapKit's MKMapView (UIKit). ▶️ Usage Add as a dependecy to your project using Swift Package Manager. Embed map vi

Dariusz Rybicki 1 Apr 4, 2022
(Animate CSS) animations for iOS. An easy to use library of iOS animations. As easy to use as an easy thing.

wobbly See Wobbly in action (examples) Add a drop of honey ?? to your project wobbly has a bunch of cool, fun, and easy to use iOS animations for you

Sagaya Abdulhafeez 150 Dec 23, 2021
(Animate CSS) animations for iOS. An easy to use library of iOS animations. As easy to use as an easy thing.

wobbly See Wobbly in action (examples) Add a drop of honey ?? to your project wobbly has a bunch of cool, fun, and easy to use iOS animations for you

Sagaya Abdulhafeez 150 Dec 23, 2021
Letters animation allows you to click on different letters and accordingly it will animate letters in a cool way. It has a very attractive UI and is very easy to use.

Letters Animation Cool Letters Animation in iOS written in Swift. Preview Table of content :- Description How to add in your project Requirement Licen

MindInventory 31 Oct 4, 2022
Numbers animation allows you to click on different numbers and accordingly it will animate numbers in a cool way. It has a very attractive UI and is very easy to use.

Numbers Animation Cool Numbers Animation in iOS written in Swift. Preview Table of content :- Description How to add in your project Requirement Licen

MindInventory 31 Oct 4, 2022
Reading animation allows you to click on the different page numbers and accordingly it will animate page changes in a cool way. It has a very attractive UI and is very easy to use.

Reading Animation Cool Reading Animation in iOS written in Swift. Preview Table of content :- Description How to add in your project Requirement Licen

MindInventory 42 Oct 4, 2022
A collection of animations for iOS. Simple, just add water animations.

DCAnimationKit A collection of animations for iOS Simply, just add water! DCAnimationKit is a category on UIView to make animations easy to perform. E

Dalton 797 Sep 23, 2022