iOS 10中的地图应用程序现在在MKUserLocation
MKAnnotationView
上有一个标题方向箭头。有什么方法可以在我自己的应用程序中添加到MKMapView
中吗?
编辑:,我很乐意手动做这件事,但我不确定这是否可能?我是否可以在地图上添加一个注释,并让它跟随用户的位置,包括动画动作?
发布于 2016-10-10 05:47:00
我通过在MKUserLocation
annotationView中添加一个子视图来解决这个问题,如下所示
func mapView(mapView: MKMapView, didAddAnnotationViews views: [MKAnnotationView]) {
if annotationView.annotation is MKUserLocation {
addHeadingViewToAnnotationView(annotationView)
}
}
func addHeadingViewToAnnotationView(annotationView: MKAnnotationView) {
if headingImageView == nil {
if let image = UIImage(named: "icon-location-heading-arrow") {
let headingImageView = UIImageView()
headingImageView.image = image
headingImageView.frame = CGRectMake((annotationView.frame.size.width - image.size.width)/2, (annotationView.frame.size.height - image.size.height)/2, image.size.width, image.size.height)
self.headingImageView = headingImageView
}
}
headingImageView?.removeFromSuperview()
if let headingImageView = headingImageView {
annotationView.insertSubview(headingImageView, atIndex: 0)
}
//use CoreLocation to monitor heading here, and rotate headingImageView as required
}
发布于 2016-11-25 15:55:39
我也经历过同样的问题(需要一个定位指示器而不用地图旋转,类似于Apple Maps应用程序)。不幸的是,苹果公司还没有推出“标题的蓝色图标”API。
我从@alku83 83的实现中创建了以下解决方案。
var headingImageView: UIImageView?
添加到类中。这主要用于转换/旋转蓝色箭头图像。CLLocationManagerDelegate
协议
惰性变量locationManager: CLLocationManager ={ let manager = CLLocationManager() //在这里设置管理器属性manager.delegate = self返回管理器}()locationManager.startUpdatingHeading()
,并且它在适当的locationManager.stopUpdatingHeading()
时停止跟踪。var userHeading: CLLocationDirection?
,它将保存方向值发布于 2016-10-07 14:20:57
是的,你可以手动完成。
其基本思想是使用CLLocationManager
跟踪用户的位置,并使用它的数据在地图上放置和旋转注释视图。
这是密码。我省略了一些与这个问题没有直接关系的东西(例如,我假设用户已经授权您的应用程序访问位置,等等),所以您可能想修改一下这段代码。
ViewController.swift
import UIKit
import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
@IBOutlet var mapView: MKMapView!
lazy var locationManager: CLLocationManager = {
let manager = CLLocationManager()
manager.delegate = self
return manager
}()
var userLocationAnnotation: UserLocationAnnotation!
override func viewDidLoad() {
super.viewDidLoad()
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.startUpdatingHeading()
locationManager.startUpdatingLocation()
userLocationAnnotation = UserLocationAnnotation(withCoordinate: CLLocationCoordinate2D(), heading: 0.0)
mapView.addAnnotation(userLocationAnnotation)
}
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
userLocationAnnotation.heading = newHeading.trueHeading
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
userLocationAnnotation.coordinate = locations.last!.coordinate
}
public func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? UserLocationAnnotation {
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "UserLocationAnnotationView") ?? UserLocationAnnotationView(annotation: annotation, reuseIdentifier: "UserLocationAnnotationView")
return annotationView
} else {
return MKPinAnnotationView(annotation: annotation, reuseIdentifier: nil)
}
}
}
在这里,我们正在做地图视图的基本设置,并开始跟踪用户的位置和使用CLLocationManager
的标题。
UserLocationAnnotation.swift
import UIKit
import MapKit
class UserLocationAnnotation: MKPointAnnotation {
public init(withCoordinate coordinate: CLLocationCoordinate2D, heading: CLLocationDirection) {
self.heading = heading
super.init()
self.coordinate = coordinate
}
dynamic public var heading: CLLocationDirection
}
非常简单的MKPointAnnotation
子类,能够存储标题方向。dynamic
关键字是这里的关键。它允许我们用KVO观察对heading
属性的更改。
UserLocationAnnotationView.swift
import UIKit
import MapKit
class UserLocationAnnotationView: MKAnnotationView {
var arrowImageView: UIImageView!
private var kvoContext: UInt8 = 13
override public init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
arrowImageView = UIImageView(image: #imageLiteral(resourceName: "Black_Arrow_Up.svg"))
addSubview(arrowImageView)
setupObserver()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
arrowImageView = UIImageView(image: #imageLiteral(resourceName: "Black_Arrow_Up.svg"))
addSubview(arrowImageView)
setupObserver()
}
func setupObserver() {
(annotation as? UserLocationAnnotation)?.addObserver(self, forKeyPath: "heading", options: [.initial, .new], context: &kvoContext)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &kvoContext {
let userLocationAnnotation = annotation as! UserLocationAnnotation
UIView.animate(withDuration: 0.2, animations: { [unowned self] in
self.arrowImageView.transform = CGAffineTransform(rotationAngle: CGFloat(userLocationAnnotation.heading / 180 * M_PI))
})
}
}
deinit {
(annotation as? UserLocationAnnotation)?.removeObserver(self, forKeyPath: "heading")
}
}
MKAnnotationView
子类,它对heading
属性进行观察,然后将适当的旋转转换设置为它的子视图(在我的例子中,它只是一个带有箭头的图像。您可以创建更复杂的注释视图,只旋转其中的某些部分,而不是整个视图。)
UIView.animate
是可选的。它的加入,使旋转更平稳。CLLocationManager
无法以每秒60次的速度观察航向值,因此当旋转速度较快时,动画可能有点不稳定。UIView.animate
调用解决了这个小问题。
coordinate
值更新的正确处理已经在MKPointAnnotation
、MKAnnotationView
和MKMapView
类中为我们实现了,因此我们不必自己动手。
https://stackoverflow.com/questions/39762732
复制相似问题