(一)添加默认样式点标记
- iOS SDK提供的大头针标注MAPinAnnotationView,通过它可以设置大头针颜色、是否显示动画、是否支持长按后拖拽大头针改变坐标等。
** - **这里用到的类是
MAPinAnnotationView
让我们对它的属性有个了解。
** 继承关系图:

属性图:
iOS SDK提供的大头针标注MAPinAnnotationView,通过它可以设置大头针颜色、是否显示动画、是否支持长按后拖拽大头针改变坐标等。在地图上添加大头针标注的步骤如下:
(1) 修改ViewController.m文件,在viewDidAppear方法中添加如下所示代码添加标注数据对象。
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
MAPointAnnotation *pointAnnotation = [[MAPointAnnotation alloc] init];
pointAnnotation.coordinate = CLLocationCoordinate2DMake(39.989631, 116.481018);
pointAnnotation.title = @"方恒国际";
pointAnnotation.subtitle = @"阜通东大街6号";
[_mapView addAnnotation:pointAnnotation];
}
(2) 实现 协议中的 mapView:viewForAnnotation:回调函数,设置标注样式。如下所示:
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id <MAAnnotation>)annotation
{
if ([annotation isKindOfClass:[MAPointAnnotation class]])
{
static NSString *pointReuseIndentifier = @"pointReuseIndentifier";
MAPinAnnotationView*annotationView = (MAPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
if (annotationView == nil)
{
annotationView = [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
}
annotationView.canShowCallout= YES; //设置气泡可以弹出,默认为NO
annotationView.animatesDrop = YES; //设置标注动画显示,默认为NO
annotationView.draggable = YES; //设置标注可以拖动,默认为NO
annotationView.pinColor = MAPinAnnotationColorPurple;
return annotationView;
}
return nil;
}
(二)自定义标注图标
- 若大头针样式的标注不能满足您的需求,您可以自定义标注图标
其实就是修改一下MAAnnotationView 的 image 属性
步骤:
**(1) 添加标注数据对象,可参考大头针标注的步骤(1)。
(2) 导入标记图片文件到工程中。这里我们导入一个名为 restauant.png 的图片文件。
(3) 在 协议的回调函数mapView:viewForAnnotation:中修改 MAAnnotationView 对应的标注图片。示例代码如下:**
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation
{
if ([annotation isKindOfClass:[MAPointAnnotation class]])
{
static NSString *reuseIndetifier = @"annotationReuseIndetifier";
MAAnnotationView *annotationView = (MAAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseIndetifier];
if (annotationView == nil)
{
annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:reuseIndetifier];
}
annotationView.image = [UIImage imageNamed:@"restaurant"];
//设置中心点偏移,使得标注底部中间点成为经纬度对应点
annotationView.centerOffset = CGPointMake(0, -18);
return annotationView;
}
return nil;
}
(三)添加自定义气泡
- 气泡在iOS中又称为callout,它由背景和气泡内容构成,如下图所示:

思路:
我们点击标注可以弹出气泡
是利用了MAAnnotationView 的这个方法
- (void) setSelected:animated:
我们需要重写这个方法,选中时新建并添加气泡视图,传入数据;非选中时删除气泡视图。
**
1.自定义一个气泡视图
2.定义MAAnnotationView 的子类,重写 setSelected:animated: 方法
3.修改ViewController.m,在MAMapViewDelegate的回调方法mapView:viewForAnnotation中的修改annotationView的类型
**
1.每个气泡显示的内容是根据您的需求定义的,这里我们按照如上图所示的气泡介绍实现一个自定义气泡的步骤:
(1) 新建自定义气泡类 CustomCalloutView,继承 UIView。
(2) 在 CustomCalloutView.h 中定义数据属性,包含:图片、商户名和商户地址。
@interface CustomCalloutView : UIView
@property (nonatomic, strong) UIImage *image; //商户图
@property (nonatomic, copy) NSString *title; //商户名
@property (nonatomic, copy) NSString *subtitle; //地址
@end
(3) 在CustomCalloutView.m中重写UIView的drawRect方法,绘制弹出气泡的背景。
#define kArrorHeight 10
- (void)drawRect:(CGRect)rect
{
[self drawInContext:UIGraphicsGetCurrentContext()];
self.layer.shadowColor = [[UIColor blackColor] CGColor];
self.layer.shadowOpacity = 1.0;
self.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
}
- (void)drawInContext:(CGContextRef)context
{
CGContextSetLineWidth(context, 2.0);
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:0.8].CGColor);
[self getDrawPath:context];
CGContextFillPath(context);
}
- (void)getDrawPath:(CGContextRef)context
{
CGRect rrect = self.bounds;
CGFloat radius = 6.0;
CGFloat minx = CGRectGetMinX(rrect),
midx = CGRectGetMidX(rrect),
maxx = CGRectGetMaxX(rrect);
CGFloat miny = CGRectGetMinY(rrect),
maxy = CGRectGetMaxY(rrect)-kArrorHeight;
CGContextMoveToPoint(context, midx+kArrorHeight, maxy);
CGContextAddLineToPoint(context,midx, maxy+kArrorHeight);
CGContextAddLineToPoint(context,midx-kArrorHeight, maxy);
CGContextAddArcToPoint(context, minx, maxy, minx, miny, radius);
CGContextAddArcToPoint(context, minx, minx, maxx, miny, radius);
CGContextAddArcToPoint(context, maxx, miny, maxx, maxx, radius);
CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
CGContextClosePath(context);
}
(4) 定义用于显示气泡内容的控件,并添加到SubView中。
如上图所示气泡,我们需要一个UIImageView和两个UILabel,添加方法如下:
#define kPortraitMargin 5
#define kPortraitWidth 70
#define kPortraitHeight 50
#define kTitleWidth 120
#define kTitleHeight 20
@interface CustomCalloutView ()
@property (nonatomic, strong) UIImageView *portraitView;
@property (nonatomic, strong) UILabel *subtitleLabel;
@property (nonatomic, strong) UILabel *titleLabel;
@end
@implementation CustomCalloutView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.backgroundColor = [UIColor clearColor];
[self initSubViews];
}
return self;
}
- (void)initSubViews
{
// 添加图片,即商户图
self.portraitView = [[UIImageView alloc] initWithFrame:CGRectMake(kPortraitMargin, kPortraitMargin, kPortraitWidth, kPortraitHeight)];
self.portraitView.backgroundColor = [UIColor blackColor];
[self addSubview:self.portraitView];
// 添加标题,即商户名
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(kPortraitMargin * 2 + kPortraitWidth, kPortraitMargin, kTitleWidth, kTitleHeight)];
self.titleLabel.font = [UIFont boldSystemFontOfSize:14];
self.titleLabel.textColor = [UIColor whiteColor];
self.titleLabel.text = @"titletitletitletitle";
[self addSubview:self.titleLabel];
// 添加副标题,即商户地址
self.subtitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(kPortraitMargin * 2 + kPortraitWidth, kPortraitMargin * 2 + kTitleHeight, kTitleWidth, kTitleHeight)];
self.subtitleLabel.font = [UIFont systemFontOfSize:12];
self.subtitleLabel.textColor = [UIColor lightGrayColor];
self.subtitleLabel.text = @"subtitleLabelsubtitleLabelsubtitleLabel";
[self addSubview:self.subtitleLabel];
}
(5) 在CustomCalloutView.m中给控件传入数据。
- (void)setTitle:(NSString *)title
{
self.titleLabel.text = title;
}
- (void)setSubtitle:(NSString *)subtitle
{
self.subtitleLabel.text = subtitle;
}
- (void)setImage:(UIImage *)image
{
self.portraitView.image = image;
}
2.自定义AnnotationView,步骤如下:
(1) 新建类CustomAnnotationView,继承MAAnnotationView或MAPinAnnotationView。若继承MAAnnotationView,则需要设置标注图标;若继承MAPinAnnotationView,使用默认的大头针标注
(2) 在CustomAnnotationView.h中定义自定义气泡属性,代码如下所示:
#import "CustomCalloutView.h"
@interface CustomAnnotationView : MAAnnotationView
@property (nonatomic, readonly) CustomCalloutView *calloutView;
@end
(3) 在CustomAnnotationView.m中修改calloutView属性,如下:
@interface CustomAnnotationView ()
@property (nonatomic, strong, readwrite) CustomCalloutView *calloutView;
@end
(4) 重写选中方法setSelected。选中时新建并添加calloutView,传入数据;非选中时删除calloutView。
#define kCalloutWidth 200.0
#define kCalloutHeight 70.0
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
if (self.selected == selected)
{
return;
}
if (selected)
{
if (self.calloutView == nil)
{
self.calloutView = [[CustomCalloutView alloc] initWithFrame:CGRectMake(0, 0, kCalloutWidth, kCalloutHeight)];
self.calloutView.center = CGPointMake(CGRectGetWidth(self.bounds) / 2.f + self.calloutOffset.x,
-CGRectGetHeight(self.calloutView.bounds) / 2.f + self.calloutOffset.y);
}
self.calloutView.image = [UIImage imageNamed:@"building"];
self.calloutView.title = self.annotation.title;
self.calloutView.subtitle = self.annotation.subtitle;
[self addSubview:self.calloutView];
}
else
{
[self.calloutView removeFromSuperview];
}
[super setSelected:selected animated:animated];
}
注意:提前导入building.png图片。
**
3.修改ViewController.m
**
在MAMapViewDelegate的回调方法mapView:viewForAnnotation中的修改annotationView的类型,代码如下:
#import “CustomAnnotationView.h”
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation
{
if ([annotation isKindOfClass:[MAPointAnnotation class]])
{
static NSString *reuseIndetifier = @"annotationReuseIndetifier";
CustomAnnotationView *annotationView = (CustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseIndetifier];
if (annotationView == nil)
{
annotationView = [[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseIndetifier];
}
annotationView.image = [UIImage imageNamed:@"restaurant"];
// 设置为NO,用以调用自定义的calloutView
annotationView.canShowCallout = NO;
// 设置中心点偏移,使得标注底部中间点成为经纬度对应点
annotationView.centerOffset = CGPointMake(0, -18);
return annotationView;
}
return nil;
}