我有MKPointAnnotation
:
let ann = MKPointAnnotation()
self.ann.coordinate = annLoc
self.ann.title = "Customize me"
self.ann.subtitle = "???"
self.mapView.addAnnotation(ann)
看起来像这样:
如何自定义此标注视图以创建自己的视图而非预定义的视图?
答案 0 :(得分:66)
首先应该注意,只需调整系统提供的标注属性,即可自定义右侧和左侧附件(通过rightCalloutAccessoryView
和leftCalloutAccessoryView
),即可对标注进行最简单的更改。您可以在viewForAnnotation
中执行该配置。
在iOS 9中,我们现在可以访问detailCalloutAccessoryView
,用可能视觉丰富的视图替换标注的副标题,同时仍然享受标注气泡的自动再现(使用自动布局使这更容易)。
例如,这是一个标注,使用MKSnapshotter
为细节标注附件中的图像视图提供图像,如WWDC 2015视频What's New in MapKit中所示:
您可以通过以下方式实现此目标:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let identifier = "MyCustomAnnotation"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.canShowCallout = true
} else {
annotationView!.annotation = annotation
}
configureDetailView(annotationView!)
return annotationView
}
func configureDetailView(annotationView: MKAnnotationView) {
let width = 300
let height = 200
let snapshotView = UIView()
let views = ["snapshotView": snapshotView]
snapshotView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[snapshotView(300)]", options: [], metrics: nil, views: views))
snapshotView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[snapshotView(200)]", options: [], metrics: nil, views: views))
let options = MKMapSnapshotOptions()
options.size = CGSize(width: width, height: height)
options.mapType = .SatelliteFlyover
options.camera = MKMapCamera(lookingAtCenterCoordinate: annotationView.annotation!.coordinate, fromDistance: 250, pitch: 65, heading: 0)
let snapshotter = MKMapSnapshotter(options: options)
snapshotter.startWithCompletionHandler { snapshot, error in
if snapshot != nil {
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
imageView.image = snapshot!.image
snapshotView.addSubview(imageView)
}
}
annotationView.detailCalloutAccessoryView = snapshotView
}
如果您正在寻找更激进的重新设计标注或需要支持9之前的iOS版本,则需要更多工作。该过程需要(a)禁用默认标注; (b)当用户点击现有的注释视图(即地图上的视觉引脚)时添加自己的视图。
复杂性随后出现在标注的设计中,您必须绘制所需的所有内容。例如。如果你想绘制一个气泡来产生呼唤的弹出感觉,你必须自己做。但是如果熟悉如何绘制形状,图像,文本等,您应该能够渲染出一个能够实现所需UX的标注:
只需将视图添加为注释视图本身的子视图,并相应地调整其约束:
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
let calloutView = ...
calloutView.translatesAutoresizingMaskIntoConstraints = false
calloutView.backgroundColor = UIColor.lightGrayColor()
view.addSubview(calloutView)
NSLayoutConstraint.activateConstraints([
calloutView.bottomAnchor.constraintEqualToAnchor(view.topAnchor, constant: 0),
calloutView.widthAnchor.constraintEqualToConstant(60),
calloutView.heightAnchor.constraintEqualToConstant(30),
calloutView.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor, constant: view.calloutOffset.x)
])
}
有关创建自己的标注视图的示例,请参阅https://github.com/robertmryan/CustomMapViewAnnotationCalloutSwift。这只会添加两个标签,但它说明了您可以根据需要绘制任何形状的气泡,使用约束来指定标注的大小等。
答案 1 :(得分:2)
使用classtype MKAnnotationView
创建Cocoa文件CustomeAnnotationView.h文件
@interface CustomeAnnotationView : MKAnnotationView
@property (strong, nonatomic) UIButton *buttonCustomeCallOut;
- (void)setSelected:(BOOL)selected animated:(BOOL)animated;
@end
CustomeAnnotationView.m文件
@implementation CustomeAnnotationView
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated{
[super setSelected:selected animated:animated];
if(selected)
{
self.buttonCustomeCallOut = [UIButton buttonWithType:UIButtonTypeCustom];//iconShare//iconShareBlue
[self.buttonCustomeCallOut addTarget:self action:@selector(buttonHandlerCallOut:) forControlEvents:UIControlEventTouchDown];
[self.buttonCustomeCallOut setBackgroundColor:[UIColor blueColor]];
[self.buttonCustomeCallOut setFrame:CGRectMake(-40,-80, 100, 100)];
[self addSubview:self.buttonCustomeCallOut];
[self.buttonCustomeCallOut setUserInteractionEnabled:YES];
}
else
{
//Remove your custom view...
[self.buttonCustomeCallOut setUserInteractionEnabled:NO];
[self.buttonCustomeCallOut removeFromSuperview];
self.buttonCustomeCallOut=nil;
}
}
-(void)buttonHandlerCallOut:(UIButton*)sender{
NSLog(@"Annotation Clicked");
}
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
UIView* v = [super hitTest:point withEvent:event];
if (v != nil)
{
[self.superview bringSubviewToFront:self];
}
return v;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event
{
CGRect rec = self.bounds;
BOOL isIn = CGRectContainsPoint(rec, point);
if(!isIn)
{
for (UIView *v in self.subviews)
{
isIn = CGRectContainsPoint(v.frame, point);
if(isIn)
break;
}
}
return isIn;
}
@end
将此代码放在您想要创建客户呼叫的位置
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = @"CustAnnotation";
CustomeAnnotationView *annotationView = (CustomeAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[CustomeAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
}
annotationView.enabled = YES;
annotationView.canShowCallout = NO;
annotationView.centerOffset = CGPointMake(0,-10);//-18
return annotationView;
}
答案 2 :(得分:1)
无需创建MKAnnotationView Custom类只需创建一个空视图.xib并设计.xib作为您的要求。在UIView swift类中编写您的企业登录信息。
在
上添加视图func mapView(_ mapView:MKMapView,viewFor annotation:MKAnnotation) - &gt; MKAnnotationView? {
...
}
方法如annotationView?.detailCalloutAccessoryView = customView
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
} else {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
}
if let annotation = annotation as? HPAnnotation {
annotationView?.canShowCallout = true
let customView = Bundle.main.loadNibNamed("HPAnnotationView", owner: self, options: nil)?.first as! HPAnnotationView
customView.labelName.text = annotation.annotationTitle
annotationView?.detailCalloutAccessoryView = customView
}
return annotationView
}
如果你想在callout视图上显示动态值,那么首先制作MKAnnotation自定义类,你可以根据需要传递对象。
import MapKit
import AddressBook
import UIKit
class HPAnnotation: NSObject, MKAnnotation {
let title: String?
let annotationTitle: String
init(title: String, annotationTitle: String = "") {
self.title = title
self.annotationTitle = annotationTitle
}
var subtitle: String? {
return details
}
}
并在创建注释时传递值
for index in 0..<searchPeopleArray.count {
let annotation = HPAnnotation(title: "", annotationTitle: "")
mapView.addAnnotation(annotation)
}
N.B:这里HPAnnotationView是我的自定义视图类和xib名称。 HPAnnotation是我的自定义MKAnnotation。