日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ios 一步一步学会自定义地图吹出框(CalloutView)--(百度地图,高德地图,google地图)

發(fā)布時(shí)間:2024/9/30 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ios 一步一步学会自定义地图吹出框(CalloutView)--(百度地图,高德地图,google地图) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言


在ios上邊使用地圖庫的同學(xué)肯定遇到過這樣的問題:吹出框只能設(shè)置title和subtitle和左右的view,不管是百度地圖還是高德地圖還是自帶的google地圖,只提供了這四個(gè)屬性,如果想添加更多的view,只能自定義。可是,類庫只能看到.h文件,.m都看不到,這讓新手比較蛋疼,龐大的地圖類庫一時(shí)半會(huì)摸不著頭腦,從頭再學(xué)還需要時(shí)間,本文就教大家快速制作一個(gè)屬于自己的 CalloutView!等你一步一步調(diào)通后,再回過頭來使用系統(tǒng)自帶的方法設(shè)置callout,就會(huì)領(lǐng)悟這個(gè)過程。




正文


Xcode版本:4.6.1


SDK版本:6.0?


百度地圖版本:1.2.2(關(guān)于地圖不必糾結(jié),無論是百度還是高德還是google都是基于系統(tǒng)的MapKit,都是一樣的)


demo模式:非ARC,使用storyboard。


demo資源:

http://download.csdn.net/detail/mad1989/5252037


Step1

創(chuàng)建demo,并添加百度地圖的靜態(tài)類庫,helloword能顯示mapview


關(guān)于這一步我專門寫了教程,這里就不再贅述,同樣,關(guān)于如何使用自帶的BMKPointAnnotation添加一個(gè)marker,我也不再說了,如果連這個(gè)你都不會(huì),那么先去官網(wǎng)看一下基本教程。


Step2

實(shí)現(xiàn)三個(gè)委托方法:

這個(gè)方法類似tableview添加cell,都是創(chuàng)建annotation

[cpp]?view plaincopy
  • #pragma?mark??
  • #pragma?mark?-?BMKMapview?delegate??
  • -(BMKAnnotationView?*)mapView:(BMKMapView?*)mapView?viewForAnnotation:(id<BMKAnnotation>)annotation;??

  • 這個(gè)方法在點(diǎn)擊地圖marker時(shí)所觸發(fā)(并顯示callout)
    [cpp]?view plaincopy
  • -(void)mapView:(BMKMapView?*)mapView?didSelectAnnotationView:(BMKAnnotationView?*)view;??

  • 這個(gè)方法在點(diǎn)擊地圖任意位置,相當(dāng)于隱藏callout

    [cpp]?view plaincopy
  • -(void)mapView:(BMKMapView?*)mapView?didDeselectAnnotationView:(BMKAnnotationView?*)view;??


  • 原理:地圖上的marker是在viewForAnnoation里創(chuàng)建的,同時(shí)也會(huì)隱含的為我們創(chuàng)建一個(gè)CalloutView,就是自帶的吹出框,只是我們看不到源碼。其實(shí)這個(gè)吹出框(CalloutView)也是一個(gè)annotation,也會(huì)在viewForAnnotation里被創(chuàng)建,他的坐標(biāo)應(yīng)該和這個(gè)點(diǎn)的marker坐標(biāo)一樣,只要明白了這一點(diǎn),就行了,marker和吹出框是兩個(gè)不同的annotation,他們有同樣的coordinate


    Step3

    自定義一個(gè)Annotation,為了簡單方便,我就直接繼承了mapview自帶的BMKPointAnnotation,這是一個(gè)經(jīng)典的圖釘marker。


    在這里我添加了一個(gè)Dictionary屬性,目的是為了自定義的CalloutView吹出框顯示內(nèi)容賦值,一會(huì)就明白了。



    Step4

    添加自定義Annotation到mapview

    [cpp]?view plaincopy
  • //添加自定義Annotation??
  • ?CLLocationCoordinate2D?center?=?{39.91669,116.39716};??
  • ??
  • CustomPointAnnotation?*pointAnnotation?=?[[CustomPointAnnotation?alloc]?init];??
  • pointAnnotation.title?=?@"我是中國人";//因?yàn)槔^承了BMKPointAnnotation,所以這些title,subtitle都可以設(shè)置??
  • pointAnnotation.subtitle?=?@"我愛自己的祖國";??
  • ??
  • pointAnnotation.coordinate?=?center;??
  • [mymapview?addAnnotation:pointAnnotation];??
  • [pointAnnotation?release];??

  • 在viewForanntion里,由于我對marker沒太大要求,直接使用了 BMKPinAnnotationView(圖釘),簡單設(shè)置image屬性為自己需要的圖標(biāo),如下所示:


    展示一個(gè)效果圖:


    顯然CalloutView只能設(shè)置title和subtitle,無法滿足我們的要求,那么繼續(xù)下一步。


    Step5

    創(chuàng)建一個(gè)(自定義的CalloutView)的Annotation,相當(dāng)于顯示calloutView的annotation。

    [注意] 繼承自NSObject<BMKAnnotation>

    CalloutMapAnnotation.h

    [cpp]?view plaincopy
  • #import?<Foundation/Foundation.h>??
  • #import?"BMapKit.h"??
  • ??
  • @interface?CalloutMapAnnotation?:?NSObject<BMKAnnotation>??
  • ??
  • ??
  • @property?(nonatomic)?CLLocationDegrees?latitude;??
  • @property?(nonatomic)?CLLocationDegrees?longitude;??
  • ??
  • ??
  • @property(retain,nonatomic)?NSDictionary?*locationInfo;//callout吹出框要顯示的各信息??
  • ??
  • ??
  • ??
  • -?(id)initWithLatitude:(CLLocationDegrees)lat?andLongitude:(CLLocationDegrees)lon;??
  • ??
  • ??
  • ??
  • @end??

  • CalloutMapAnnotation.m

    [cpp]?view plaincopy
  • #import?"CalloutMapAnnotation.h"??
  • ??
  • @implementation?CalloutMapAnnotation??
  • ??
  • ??
  • @synthesize?latitude;??
  • @synthesize?longitude;??
  • @synthesize?locationInfo;??
  • ??
  • -?(id)initWithLatitude:(CLLocationDegrees)lat??
  • ??????????andLongitude:(CLLocationDegrees)lon?{??
  • ????if?(self?=?[super?init])?{??
  • ????????self.latitude?=?lat;??
  • ????????self.longitude?=?lon;??
  • ????}??
  • ????return?self;??
  • }??
  • ??
  • ??
  • -(CLLocationCoordinate2D)coordinate{??
  • ??
  • ????CLLocationCoordinate2D?coordinate;??
  • ????coordinate.latitude?=?self.latitude;??
  • ????coordinate.longitude?=?self.longitude;??
  • ????return?coordinate;??
  • ??????
  • ??
  • }??
  • ??
  • ??
  • @end??

  • 這里設(shè)置了經(jīng)緯度的屬性,和一個(gè)init初始化經(jīng)緯度的方法(經(jīng)緯度=marker的經(jīng)緯度),同樣添加了一個(gè)Dictionary的屬性,為了傳遞在CalloutView上內(nèi)容的賦值,繼續(xù)。


    Step6

    這一步我們創(chuàng)建自定義的View,想要什么布局就寫什么樣的布局,想要多少屬性就加多少屬性,這里我使用了code方式畫了一個(gè)contentView,里面的子view使用Xib方式創(chuàng)建。

    [注意:繼承自BMKAnnotationView]


    CallOutAnnotationView.h

    [cpp]?view plaincopy
  • #import?"BMKAnnotationView.h"??
  • #import?"BusPointCell.h"??
  • ??
  • @interface?CallOutAnnotationView?:?BMKAnnotationView??
  • ??
  • ??
  • @property(nonatomic,retain)?UIView?*contentView;??
  • ??
  • //添加一個(gè)UIView??
  • @property(nonatomic,retain)?BusPointCell?*busInfoView;//在創(chuàng)建calloutView?Annotation時(shí),把contentView?add的?subview賦值給businfoView??
  • ??
  • ??
  • @end??

  • BusPointCell是ContentView里的subview,這個(gè)view就是顯示各個(gè)組件,并賦不同的值

    CallOutAnnotationView.m

    [cpp]?view plaincopy
  • #import?"CallOutAnnotationView.h"??
  • #import?<QuartzCore/QuartzCore.h>??
  • ??
  • ??
  • #define??Arror_height?6??
  • ??
  • @implementation?CallOutAnnotationView??
  • @synthesize?contentView;??
  • @synthesize?busInfoView;??
  • ??
  • -?(id)initWithFrame:(CGRect)frame??
  • {??
  • ????self?=?[super?initWithFrame:frame];??
  • ????if?(self)?{??
  • ????}??
  • ????return?self;??
  • }??
  • ??
  • -(void)dealloc{??
  • ????[contentView?release];??
  • ????[busInfoView?release];??
  • ????[super?dealloc];??
  • }??
  • ??
  • -(id)initWithAnnotation:(id<BMKAnnotation>)annotation?reuseIdentifier:(NSString?*)reuseIdentifier{??
  • ??
  • ??????
  • ????self?=?[super?initWithAnnotation:annotation?reuseIdentifier:reuseIdentifier];??
  • ????if?(self)?{??
  • ????????self.backgroundColor?=?[UIColor?clearColor];??
  • ????????self.canShowCallout?=?NO;??
  • ????????self.centerOffset?=?CGPointMake(0,?-55);??
  • ????????self.frame?=?CGRectMake(0,?0,?240,?80);??
  • ??
  • ????????UIView?*_contentView?=?[[UIView?alloc]?initWithFrame:CGRectMake(5,?5,?self.frame.size.width-15,?self.frame.size.height-15)];??
  • ????????_contentView.backgroundColor???=?[UIColor?clearColor];??
  • ????????[self?addSubview:_contentView];??
  • ????????self.contentView?=?_contentView;??
  • ????????[_contentView?release];??
  • ????}??
  • ????return?self;??
  • ??
  • }??
  • ??
  • -(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:255.0/255.0?green:255.0/255.0?blue:255.0/255.0?alpha:1.0].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),??
  • ????//?midy?=?CGRectGetMidY(rrect),??
  • ????maxy?=?CGRectGetMaxY(rrect)-Arror_height;??
  • ????CGContextMoveToPoint(context,?midx+Arror_height,?maxy);??
  • ????CGContextAddLineToPoint(context,midx,?maxy+Arror_height);??
  • ????CGContextAddLineToPoint(context,midx-Arror_height,?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);??
  • }??
  • ??
  • ??
  • ??
  • @end??

  • BusPointCell.h

    想要多少label,就可以有多少label

    [cpp]?view plaincopy
  • #import?<UIKit/UIKit.h>??
  • ??
  • @interface?BusPointCell?:?UIView??
  • @property?(retain,?nonatomic)?IBOutlet?UILabel?*aliasLabel;??
  • @property?(retain,?nonatomic)?IBOutlet?UILabel?*speedLabel;??
  • @property?(retain,?nonatomic)?IBOutlet?UILabel?*degreeLabel;??
  • @property?(retain,?nonatomic)?IBOutlet?UILabel?*nameLabel;??
  • ??
  • @end??

  • BusPointCell.m

    [cpp]?view plaincopy
  • #import?"BusPointCell.h"??
  • ??
  • @implementation?BusPointCell??
  • ??
  • -?(id)initWithFrame:(CGRect)frame??
  • {??
  • ????self?=?[super?initWithFrame:frame];??
  • ????if?(self)?{??
  • ??
  • ????}??
  • ????return?self;??
  • }??
  • -?(void)dealloc?{??
  • ????[_aliasLabel?release];??
  • ????[_speedLabel?release];??
  • ????[_degreeLabel?release];??
  • ????[_nameLabel?release];??
  • ????[super?dealloc];??
  • }??
  • @end??

  • BusPointCell.xib




    Step7

    自定義的CalloutView都準(zhǔn)備妥當(dāng),現(xiàn)在就是要實(shí)現(xiàn)他們的部分了,簡單說一下原理,在didSelectAnnotationView函數(shù)里創(chuàng)建并添加calloutview的annotation(CalloutMapAnnotation),然后在viewForAnnotation函數(shù)內(nèi)實(shí)例化要顯示的calloutview(CallOutAnnotationView)


    首先聲明一個(gè)局部變量CalloutMapAnnotation?*_calloutMapAnnotation;

    在didSelectAnnotationView函數(shù)內(nèi)添加如下代碼:

    [cpp]?view plaincopy
  • //CustomPointAnnotation?是自定義的marker標(biāo)注點(diǎn),通過這個(gè)來得到添加marker時(shí)設(shè)置的pointCalloutInfo屬性??
  • CustomPointAnnotation?*annn?=?(CustomPointAnnotation*)view.annotation;??
  • ??
  • ??
  • if?([view.annotation?isKindOfClass:[CustomPointAnnotation?class]])?{??
  • ??????
  • ????//如果點(diǎn)到了這個(gè)marker點(diǎn),什么也不做??
  • ????if?(_calloutMapAnnotation.coordinate.latitude?==?view.annotation.coordinate.latitude&&??
  • ????????_calloutMapAnnotation.coordinate.longitude?==?view.annotation.coordinate.longitude)?{??
  • ????????return;??
  • ????}??
  • ????//如果當(dāng)前顯示著calloutview,又觸發(fā)了select方法,刪除這個(gè)calloutview?annotation??
  • ????if?(_calloutMapAnnotation)?{??
  • ????????[mapView?removeAnnotation:_calloutMapAnnotation];??
  • ????????_calloutMapAnnotation=nil;??
  • ??????????
  • ????}??
  • ????//創(chuàng)建搭載自定義calloutview的annotation??
  • ????_calloutMapAnnotation?=?[[[CalloutMapAnnotation?alloc]?initWithLatitude:view.annotation.coordinate.latitude?andLongitude:view.annotation.coordinate.longitude]?autorelease];??
  • ??????
  • ????//把通過marker(ZNBCPointAnnotation)設(shè)置的pointCalloutInfo信息賦值給CalloutMapAnnotation??
  • ????_calloutMapAnnotation.locationInfo?=?annn.pointCalloutInfo;??
  • ??????
  • ????[mapView?addAnnotation:_calloutMapAnnotation];??
  • ??
  • ??????
  • ??????
  • ????[mapView?setCenterCoordinate:view.annotation.coordinate?animated:YES];??
  • ??????
  • }??


  • 其次,要在viewForAnnotation里創(chuàng)建我們的calloutview(CallOutAnnotationView),添加如下代碼:

    [cpp]?view plaincopy
  • else?if?([annotation?isKindOfClass:[CalloutMapAnnotation?class]]){??
  • ??????
  • ????//此時(shí)annotation就是我們calloutview的annotation??
  • ????CalloutMapAnnotation?*ann?=?(CalloutMapAnnotation*)annotation;??
  • ??????
  • ????//如果可以重用??
  • ????CallOutAnnotationView?*calloutannotationview?=?(CallOutAnnotationView?*)[mapView?dequeueReusableAnnotationViewWithIdentifier:@"calloutview"];??
  • ??????
  • ????//否則創(chuàng)建新的calloutView??
  • ????if?(!calloutannotationview)?{??
  • ????????calloutannotationview?=?[[[CallOutAnnotationView?alloc]?initWithAnnotation:annotation?reuseIdentifier:@"calloutview"]?autorelease];??
  • ??
  • ????????BusPointCell?*cell?=?[[[NSBundle?mainBundle]?loadNibNamed:@"BusPointCell"?owner:self?options:nil]?objectAtIndex:0];??
  • ??????????
  • ????????[calloutannotationview.contentView?addSubview:cell];??
  • ????????calloutannotationview.busInfoView?=?cell;??
  • ????}??
  • ??????
  • ????//開始設(shè)置添加marker時(shí)的賦值??
  • ????calloutannotationview.busInfoView.aliasLabel.text?=?[ann.locationInfo?objectForKey:@"alias"];??
  • ????calloutannotationview.busInfoView.speedLabel.text?=?[ann.locationInfo?objectForKey:@"speed"];??
  • ????calloutannotationview.busInfoView.degreeLabel.text?=[ann.locationInfo?objectForKey:@"degree"];??
  • ????calloutannotationview.busInfoView.nameLabel.text?=??[ann.locationInfo?objectForKey:@"name"];??
  • ??????
  • ????return?calloutannotationview;??
  • ??????
  • }??

  • [注意]在添加marker的判斷里一定要設(shè)置marker annotation.canShowCallout?=NO; 否則點(diǎn)擊marker會(huì)默認(rèn)顯示系統(tǒng)的吹出框



    Step8

    calloutview的annotation也創(chuàng)建和添加了,接下來我們就設(shè)置一下marker對應(yīng)吹出框的數(shù)據(jù):



    然后運(yùn)行一下:



    哈哈!搞定了吧,具體布局可以自己通過code方式,或xib方式設(shè)計(jì),目前點(diǎn)擊marker能顯示了,可是點(diǎn)擊其它區(qū)域還是無法顯示,所以我們在didDeselectAnnotationView方法里還需要判斷一下,remove掉。


    [cpp]?view plaincopy
  • -(void)mapView:(BMKMapView?*)mapView?didDeselectAnnotationView:(BMKAnnotationView?*)view{??
  • ??????
  • ????if?(_calloutMapAnnotation&&![view?isKindOfClass:[CallOutAnnotationView?class]])?{??
  • ??
  • ????????if?(_calloutMapAnnotation.coordinate.latitude?==?view.annotation.coordinate.latitude&&??
  • ????????????_calloutMapAnnotation.coordinate.longitude?==?view.annotation.coordinate.longitude)?{??
  • ????????????[mapView?removeAnnotation:_calloutMapAnnotation];??
  • ????????????_calloutMapAnnotation?=?nil;??
  • ????????}??
  • ??????????
  • ??????????
  • ????}??
  • ??
  • }??



  • 最后


    之所以在顯示marker的annotation[本文為CustomPointAnnotation]和顯示calloutview的annotation[本文為CalloutMapAnnotation]里各添加一個(gè)Dictionary,就是要在點(diǎn)擊時(shí)通過marker傳遞數(shù)據(jù),添加時(shí)通過calloutview的annotation實(shí)例來設(shè)置每一個(gè)屬性的數(shù)據(jù),已達(dá)到不同的maker,顯示不同的數(shù)據(jù)。


    可能我的過程不是太清晰,自己仔細(xì)研究一下這三個(gè)函數(shù)和mapview自帶的callout調(diào)用過程,便會(huì)明白



    本文轉(zhuǎn)自:http://blog.csdn.net/mad1989/article/details/8794762

    總結(jié)

    以上是生活随笔為你收集整理的ios 一步一步学会自定义地图吹出框(CalloutView)--(百度地图,高德地图,google地图)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。