Ben*_*ams 19 mkmapview ios mkuserlocation ios10
iOS 10中的地图应用程序现在包含一个标题方向箭头MKUserLocation MKAnnotationView.有什么方法可以MKMapView在我自己的应用程序中添加它吗?
编辑:我很乐意手动执行此操作,但我不确定它是否可行?我可以在地图上添加注释并让它跟随用户的位置,包括动画移动吗?
Dav*_*d T 14
我也遇到了同样的问题(需要一个方向指示器,而不需要地图旋转,类似于Apple Maps应用程序).不幸的是,Apple还没有提供'蓝色图标'标题'API.
我创建了以下@ alku83实现的解决方案.
添加委托方法以将蓝色箭头图标添加到地图位置点
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
if views.last?.annotation is MKUserLocation {
addHeadingView(toAnnotationView: views.last!)
}
}
Run Code Online (Sandbox Code Playgroud)添加方法以创建"蓝色箭头图标".
func addHeadingView(toAnnotationView annotationView: MKAnnotationView) {
if headingImageView == nil {
let image = #YOUR BLUE ARROW ICON#
headingImageView = UIImageView(image: image)
headingImageView!.frame = CGRect(x: (annotationView.frame.size.width - image.size.width)/2, y: (annotationView.frame.size.height - image.size.height)/2, width: image.size.width, height: image.size.height)
annotationView.insertSubview(headingImageView!, at: 0)
headingImageView!.isHidden = true
}
}
Run Code Online (Sandbox Code Playgroud)加入var headingImageView: UIImageView?你的班级.这主要用于变换/旋转蓝色箭头图像.
(在不同的类/对象中,具体取决于您的体系结构)创建一个位置管理器实例,该类符合CLLocationManagerDelegate协议
lazy var locationManager: CLLocationManager = {
let manager = CLLocationManager()
// Set up your manager properties here
manager.delegate = self
return manager
}()
Run Code Online (Sandbox Code Playgroud)确保您的位置管理员正在跟踪用户标题数据,locationManager.startUpdatingHeading()并在适当时停止跟踪locationManager.stopUpdatingHeading()
添加var userHeading: CLLocationDirection?哪个将保留方向值
添加委托方法以通知标题值何时更改,并相应地更改userHeading值
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
if newHeading.headingAccuracy < 0 { return }
let heading = newHeading.trueHeading > 0 ? newHeading.trueHeading : newHeading.magneticHeading
userHeading = heading
NotificationCenter.default.post(name: Notification.Name(rawValue: #YOUR KEY#), object: self, userInfo: nil)
}
Run Code Online (Sandbox Code Playgroud)现在,在符合MKMapViewDelegate的类中,添加方法以"变换"标题图像的方向
func updateHeadingRotation() {
if let heading = # YOUR locationManager instance#,
let headingImageView = headingImageView {
headingImageView.isHidden = false
let rotation = CGFloat(heading/180 * Double.pi)
headingImageView.transform = CGAffineTransform(rotationAngle: rotation)
}
}
Run Code Online (Sandbox Code Playgroud)是的,您可以手动执行此操作.
基本思想是跟踪用户的位置,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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们正在进行地图视图的基本设置,并开始跟踪用户的位置和标题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
}
Run Code Online (Sandbox Code Playgroud)
非常简单的MKPointAnnotation子类,能够存储航向.dynamic关键字是关键所在.它允许我们heading用KVO 观察属性的变化.
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")
}
}
Run Code Online (Sandbox Code Playgroud)
MKAnnotationView执行heading属性观察的子类,然后将适当的旋转变换设置为它的子视图(在我的例子中,它只是带箭头的图像.您可以创建更复杂的注释视图并仅旋转它的一部分而不是整个视图. )
UIView.animate是可选的.添加它以使旋转更平滑.CLLocationManager不能每秒观察60次航向值,因此当快速旋转时,动画可能会有点不连贯.UIView.animate电话解决了这个小问题.
妥善处理coordinate值更新已经实施了MKPointAnnotation,MKAnnotationView和MKMapView我们班的,所以我们不必自己动手.
我通过向annotationView添加子视图解决了这个问题MKUserLocation,就像这样
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
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5978 次 |
| 最近记录: |