标注可以精确表示用户需要展示的位置信息,高德地图SDK提供的标注功能允许用户自定义图标和信息窗,同时提供了标注的点击、拖动事件的回调。

SDK 提供的地图标注为MAAnnotation类,不同的标记可以根据图标和改变信息窗的样式和内容加以区分。

添加默认样式点标记

iOS SDK提供的大头针标注MAPinAnnotationView,通过它可以设置大头针颜色、是否显示动画、是否支持长按后拖拽大头针改变坐标等。在地图上添加大头针标注的步骤如下:

(1) 修改ViewController.m文件,在viewDidAppear方法中添加如下所示代码添加标注数据对象。

MAPointAnnotation *pointAnnotation = [[MAPointAnnotation alloc] init];

pointAnnotation.coordinate = CLLocationCoordinate2DMake(39.989631, 116.481018);

pointAnnotation.title = @"方恒国际";

pointAnnotation.subtitle = @"阜通东大街6号";

[_mapView addAnnotation:pointAnnotation];

let pointAnnotation = MAPointAnnotation()

pointAnnotation.coordinate = CLLocationCoordinate2D(latitude: 39.979590, longitude: 116.352792)

pointAnnotation.title = "方恒国际"

pointAnnotation.subtitle = "阜通东大街6号"

mapView.addAnnotation(pointAnnotation)

(2) 实现 协议中的 mapView:viewForAnnotation:回调函数,设置标注样式。 如下所示:

- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id )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;

}

func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! {

if annotation.isKind(of: MAPointAnnotation.self) {

let pointReuseIndetifier = "pointReuseIndetifier"

var annotationView: MAPinAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: pointReuseIndetifier) as! MAPinAnnotationView?

if annotationView == nil {

annotationView = MAPinAnnotationView(annotation: annotation, reuseIdentifier: pointReuseIndetifier)

}

annotationView!.canShowCallout = true

annotationView!.animatesDrop = true

annotationView!.isDraggable = true

annotationView!.rightCalloutAccessoryView = UIButton(type: UIButtonType.detailDisclosure)

let idx = annotations.index(of: annotation as! MAPointAnnotation)

annotationView!.pinColor = MAPinAnnotationColor(rawValue: idx!%3)!

return annotationView!

}

return nil

}

运行程序,在地图显示对应的标注点,点击标注弹出气泡,效果如图:

添加自定义样式点标记

iOS SDK可自定义标注(包括自定义标注图标和 自定义气泡图标),均通过MAAnnotationView来实现。

自定义标注图标

若大头针样式的标注不能满足您的需求,您可以自定义标注图标。步骤如下:

(1) 添加标注数据对象,可参考大头针标注的步骤(1)。

(2) 导入标记图片文件到工程中。这里我们导入一个名为 restauant.png 的图片文件。

(3) 在 协议的回调函数mapView:viewForAnnotation:中修改 MAAnnotationView 对应的标注图片。示例代码如下:

- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id)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;

}

func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! {

if annotation.isKind(of: MAPointAnnotation.self) {

let pointReuseIndetifier = "pointReuseIndetifier"

var annotationView: MAAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: pointReuseIndetifier)

if annotationView == nil {

annotationView = MAAnnotationView(annotation: annotation, reuseIdentifier: pointReuseIndetifier)

}

annotationView!.image = UIImage(named: "restaurant")

//设置中心点偏移,使得标注底部中间点成为经纬度对应点

annotationView!.centerOffset = CGPoint(0, -18);

return annotationView!

}

return nil

}

运行程序,标注点变成了餐馆图标,如下所示:

添加自定义气泡

气泡在iOS中又称为callout,它由背景和气泡内容构成,如下图所示:

每个气泡显示的内容是根据您的需求定义的,这里我们按照如上图所示的气泡介绍实现一个自定义气泡的步骤,由于是高度自定义内容,以下文档中仅提供OC语言的示例:

(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);

}

override func draw(_ rect: CGRect) {

drawInContext(context: UIGraphicsGetCurrentContext()!)

self.layer.shadowColor = UIColor.black.cgColor

self.layer.shadowOpacity = 1.0

self.layer.shadowOffset = CGSize.init(width: 0.0, height: 0.0)

}

func drawInContext(context : CGContext) {

context.setLineWidth(2.0)

context.setFillColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 0.8)

getDrawPath(context: context)

context.fillPath()

}

func getDrawPath(context : CGContext) {

let kArrorHeight = 10

let rect = self.bounds

let radius = 6.0

let minx = rect.minX

let midx = rect.midX

let maxx = rect.maxX

let miny = rect.minY

let maxy = rect.maxY - 10

context.move(to: CGPoint.init(x: midx + CGFloat(kArrorHeight), y: maxy))

context.addLine(to: CGPoint.init(x: midx, y: maxy + CGFloat(kArrorHeight)))

context.addLine(to: CGPoint.init(x: midx - CGFloat(kArrorHeight), y: maxy))

context.addArc(tangent1End: CGPoint.init(x: minx, y: maxy), tangent2End: CGPoint.init(x: minx, y: miny), radius: CGFloat(radius))

context.addArc(tangent1End: CGPoint.init(x: minx, y: minx), tangent2End: CGPoint.init(x: maxx, y: miny), radius: CGFloat(radius))

context.addArc(tangent1End: CGPoint.init(x: maxx, y: miny), tangent2End: CGPoint.init(x: maxx, y: maxx), radius: CGFloat(radius))

context.addArc(tangent1End: CGPoint.init(x: maxx, y: maxy), tangent2End: CGPoint.init(x: midx, y: maxy), radius: CGFloat(radius))

context.closePath();

}

(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];

}

var portraitView : UIImageView!

var subtitleLabel : UILabel!

var titleLabel : UILabel!

override init(frame: CGRect) {

super.init(frame: frame)

initSubViews()

}

required init?(coder aDecoder: NSCoder) {

super.init(coder: aDecoder)

initSubViews()

}

func initSubViews() {

backgroundColor = UIColor.clear

let kPortraitMargin = 5.0

let kPortraitWidth = 70.0

let kPortraitHeight = 50.0

let kTitleWidth = 120.0

let kTitleHeight = 20.0

// 添加图片,即商户图

portraitView = UIImageView.init(frame: CGRect.init(x: kPortraitMargin, y: kPortraitMargin, width: kPortraitWidth, height: kPortraitHeight))

portraitView.backgroundColor = UIColor.black

addSubview(portraitView)

// 添加标题,即商户名

titleLabel = UILabel.init(frame: CGRect.init(x: kPortraitMargin * 2 + kPortraitWidth, y: kPortraitMargin, width: kTitleWidth, height: kTitleHeight))

titleLabel.font = UIFont.systemFont(ofSize: 14)

titleLabel.textColor = UIColor.white

titleLabel.text = "titletitletitletitle"

addSubview(titleLabel)

// 添加副标题,即商户地址

subtitleLabel = UILabel.init(frame: CGRect.init(x: kPortraitMargin * 2 + kPortraitWidth, y: kPortraitMargin * 2 + kTitleHeight, width: kTitleWidth, height: kTitleHeight))

subtitleLabel.font = UIFont.systemFont(ofSize: 12)

subtitleLabel.textColor = UIColor.lightGray

subtitleLabel.text = "titletitletitletitle"

addSubview(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;

}

func setTitle(title : NSString) {

titleLabel.text = title as String;

}

func setSubtitle(subtitle : NSString) {

subtitleLabel.text = subtitle as String;

}

func setImage(image : UIImage) {

portraitView.image = image;

}

以上就是自定义气泡的全部过程,但是为了在点击标注时,弹出自定义的气泡,还需要。步骤如下:

添加自定义AnnotationView

由于是高度自定义内容,以下文档中仅提供OC语言的示例:

(1) 新建类CustomAnnotationView,继承MAAnnotationView或MAPinAnnotationView。若继承MAAnnotationView,则需要设置标注图标;若继承MAPinAnnotationView,使用默认的大头针标注

(2) 在CustomAnnotationView.h中定义自定义气泡属性

代码如下所示:

#import "CustomCalloutView.h"

@interface CustomAnnotationView : MAAnnotationView

@property (nonatomic, readonly) CustomCalloutView *calloutView;

@end

func setSelected(selected: Bool, animated: Bool) {

if self.isSelected == selected{

return;

}

if selected {

if calloutView == nil {

calloutView = CustomCalloutView.init(frame: CGRect.init(x: 0, y: 0, width: 200, height: 70))

calloutView.center = CGPoint.init(x: bounds.width/2 + calloutOffset.x, y: -calloutView.bounds.height/2 + calloutOffset.y)

}

calloutView.image = UIImage.init(named: "building")

calloutView.title = annotation.title as? NSString

calloutView.subtitle = annotation.subtitle as? NSString

addSubview(calloutView)

} else {

calloutView.removeFromSuperview()

}

super.setSelected(selected, animated: animated)

}

(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图片。

(5) 修改ViewController.m,在MAMapViewDelegate的回调方法mapView:viewForAnnotation中的修改annotationView的类型

代码如下:

#import “CustomAnnotationView.h”

- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id)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;

}

func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! {

if annotation is MAPointAnnotation {

let customReuseIndetifier: String = "annotationReuseIndetifier"

var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: customReuseIndetifier) as? CustomAnnotationView

if annotationView == nil {

annotationView = CustomAnnotationView.init(annotation: annotation, reuseIdentifier: customReuseIndetifier)

}

annotationView?.image = UIImage.init(named: "restaurant")

// 设置为false,用以调用自定义的calloutView

annotationView?.canShowCallout = false

// 设置中心点偏移,使得标注底部中间点成为经纬度对应点

annotationView?.centerOffset = CGPoint.init(x: 0, y: -18)

return annotationView

}

return nil

}

运行程序,效果如下:

高德地图大头针功能_绘制点标记-在地图上绘制-开发指南-iOS 地图SDK | 高德地图API...相关推荐

  1. PHP地图规划骑行路径,骑行路线规划-路线规划-开发指南-iOS 导航SDK | 高德地图API...

    基本介绍 要实现骑行路径规划功能,以下三个类您需要了解:AMapNaviRideManager 是骑行导航管理类,提供路线规划.行前选路.导航中重算等方法.注意:从导航SDK7.4.0开始,AMapN ...

  2. vue使用高德地图画电子围栏_地理围栏-辅助功能-开发指南-iOS 定位SDK | 高德地图API...

    以下内容自 iOS 定位SDK V2.3.0 后支持. 第 1 步,引入头文件 在调用地理围栏功能的类中引入AMapFoundationKit.h和AMapLocationKit.h这两个头文件,注意 ...

  3. 设置电子围栏 高德地图_地理围栏-辅助功能-开发指南-iOS 定位SDK | 高德地图API...

    以下内容自 iOS 定位SDK V2.3.0 后支持. 第 1 步,引入头文件 在调用地理围栏功能的类中引入AMapFoundationKit.h和AMapLocationKit.h这两个头文件,注意 ...

  4. 高德sdk定位当前位置_单次定位-获取位置-开发指南-iOS 定位SDK | 高德地图API

    iOS定位SDK提供的单次定位方法基于苹果定位核心,苹果定位核心会在设备移动时连续返回定位结果,高德在此基础上封装了单次定位.当设备可以正常联网时,还可以返回该定位点的对应的中国境内位置信息(包括:省 ...

  5. ios 高德获取定位_单次定位-获取位置-开发指南-iOS 定位SDK | 高德地图API

    iOS定位SDK提供的单次定位方法基于苹果定位核心,苹果定位核心会在设备移动时连续返回定位结果,高德在此基础上封装了单次定位.当设备可以正常联网时,还可以返回该定位点的对应的中国境内位置信息(包括:省 ...

  6. 高德地图大头针功能_【iOS】高德地图MAMapKit的使用:地图显示、添加大头针、导航、定位功能介绍...

    最近在做基于高德地图的定位.导航及添加大头针的功能,特此记录下来...方便刚接触的同学参考... 一.申请 Key:获取用户Key 2.在"KEY管理"页面点击上方的"获 ...

  7. java 高德地图路线规划_公交出行路线规划-出行路线规划-开发指南-Android 地图SDK | 高德地图API...

    公交路径规划可以根据起终点和公交换乘的数据,使用 BusRouteOverlay 画出公交路线图层,包括起终点和换乘点.另外也可以自定义起终点和换乘点的图标. 目前支持跨城公交路线规划,提供不同城市之 ...

  8. 高德地图大头针功能_高德地图 (多个大头针显示)

    高德地图 运用场景:先获取本机经纬度 ,从服务端获取周围的小区和停车场的经纬度,通过服务端返回的type赋值给大头针的title来判断是小区还是停车场 1,首先实例化地图 #import #impor ...

  9. android 地图导航开发思路,基础功能-导航组件-开发指南-Android 导航SDK | 高德地图API...

    预置条件 请在您工程的 AndroidManifest.xml 中配置声明导航组件 Activity: android:name="com.amap.api.navi.AmapRouteAc ...

  10. 设置电子围栏 高德地图_地理围栏-辅助功能-开发指南-Android 定位SDK | 高德地图API...

    以下内容自定位 SDK V3.2.0 版本后支持. 第一步,创建地理围栏 地理围栏没有最大个数限制,您可以无限制的创建围栏.但请您根据业务需求合理的创建围栏,控制围栏个数可以有效的保证程序执行效率.定 ...

最新文章

  1. pyrosim有Linux版本吗,烟气流动分析软件Pyrosim版本 2020.4.092
  2. C#分隔字符串时遭遇空值
  3. 如何手动卸载 SQL Server 2005 实例(官方)
  4. 只要200行JavaScript代码,就能把特斯拉汽车带到您身边
  5. 在不了解这5种语言以后就可能永远要消失在世界上了
  6. python selenium list index out of range
  7. 是谁成全了我们在吃鸡、狼人杀里的实时互动?
  8. 解决办法:std没有成员initializer_list
  9. 谷歌浏览器历史版本下载网址
  10. android 声音控制面板,音量样式控制面板
  11. 验证码输入错误后自动刷新验证码
  12. 5角硬币中的币王,已价值16000元,谁家有?
  13. 台式计算机怎么强制关机,台式电脑怎么强制关机
  14. 蓬莱小课:零基础应届生如何转行学数据分析师?
  15. 深入剖析NVMe Over Fabrics
  16. 基于74LS148的简单四路抢答器 Multisim
  17. API接口签名生成算法和签名验证算法
  18. 搜索衬线字体和无衬线字体的区别
  19. Twitter将开通直播打赏功能 帮助美国网红赚钱
  20. ansible防火墙firewalld设置

热门文章

  1. cout和cin后面跟指针的问题
  2. 分享学JavaScript的第九天
  3. Android自动接听来电并录音
  4. matlab自动调焦,光学系统离焦对自动调焦评价函数的影响
  5. 【前端】jQuery上传图片插件 : uploadifive
  6. Qt简述如何实现不规则按钮
  7. Microsoft PPT文本框里首行缩进单位只能默认为厘米而不能设置为“字符”等其他单位?
  8. 流浪是对另一种生活的执着
  9. postfix 测试邮件服务器,搭建Postfix邮件服务器
  10. 初探 spring data(一)--- spring data 概述