IOS百度地圖BMKAnnotationView添加子視圖,子視圖點(diǎn)擊事件不響應(yīng)解決辦法

做開發(fā)有一段時(shí)間了,第一次寫文章,主要記錄下使用百度地圖中遇到的比較棘手的問題以及解決辦法,直接進(jìn)入主題吧,最近項(xiàng)目中遇到一個(gè)需求,在地圖zoomlevel較小的時(shí)候地圖標(biāo)注只顯示一個(gè)圖片,此時(shí)圖片可以點(diǎn)擊,然后顯示詳情view(數(shù)據(jù)較復(fù)雜),詳情view也有點(diǎn)擊事件,也可以點(diǎn)擊,然后彈出另一個(gè)controller,效果大致如下:

默認(rèn)顯示樣式


點(diǎn)擊顯示自定義view



點(diǎn)擊彈出view在彈出個(gè)controller

在地圖zoomlevel被放大到一定程度后,不需要點(diǎn)擊,自動(dòng)顯示所有的自定義view,效果如圖:


zoomlevel變大自動(dòng)顯示詳情view


點(diǎn)擊view彈出controller



筆者主要記錄如何解決這個(gè)需求,如何配置地圖以及定位等基礎(chǔ)功能詳情請(qǐng)參考官方文檔或者我給出的Demo都有詳細(xì)的注釋,先說下我的解決思路吧,首先拿到數(shù)據(jù)后,在地圖上將點(diǎn)都描出來(lái)(自定義view的數(shù)據(jù)信息是小圖標(biāo)的詳情,所以經(jīng)緯度是一樣的),注意是把小圖標(biāo)和自定義view都作為標(biāo)注點(diǎn)描出來(lái),通過調(diào)節(jié)centeroffset,frame等屬性使得兩個(gè)標(biāo)注的位置如上需求圖所示,

/**

隨機(jī)模擬數(shù)據(jù)

*/

- (void)getShowData:(CLLocationCoordinate2D)coor {

imagePointArr= [NSMutableArray array];

customPointArr= [NSMutableArray array];

NSMutableArray*dataArr = [NSMutableArray array];

for(inti =0; i <20; i++) {

doublelat =(arc4random() %100) *0.001f;

doublelon =(arc4random() %100) *0.001f;

//為了保證數(shù)據(jù)一樣,所以用數(shù)組將隨機(jī)產(chǎn)生的將緯度存起來(lái)

CLLocationCoordinate2D coorrr =CLLocationCoordinate2DMake(coor.latitude+ lat, coor.longitude+ lon);

NSDictionary *latLonDic =@{@"lat":[NSStringstringWithFormat:@"%f",coorrr.latitude],@"lon":[NSString stringWithFormat:@"%f",coorrr.longitude]};

[dataArr addObject:latLonDic];

customPointAnnotation= [[BMKPointAnnotation alloc]init];

customPointAnnotation.coordinate= coorrr;

customPointAnnotation.title= [NSString stringWithFormat:@"%d",i];

[customPointArr ?addObject:customPointAnnotation];

[_mapView ?addAnnotation:customPointAnnotation];

BMKAnnotationView *detailView = [_mapView viewForAnnotation:customPointAnnotation];

detailView.tag=20000+ i;

}

//用兩個(gè)for循環(huán)是為了保證自定義的annotionview點(diǎn)在最下面,(先添加的點(diǎn)在地圖最下方,安卓有一個(gè)屬性可以設(shè)置覆蓋物層級(jí)關(guān)系,但是ios目前還沒有這個(gè)屬性)

for(inti =0; i <20; i++) {

CLLocationCoordinate2D ?coorrr =CLLocationCoordinate2DMake([dataArr[i][@"lat"]doubleValue], [dataArr[i][@"lon"]doubleValue]);

imagePointAnnotation= [[BMKPointAnnotation alloc]init];

imagePointAnnotation.coordinate= coorrr;

imagePointAnnotation.title= [NSStringstringWithFormat:@"%d",i];

[imagePointArr ?addObject:imagePointAnnotation];

[_mapView ?addAnnotation:imagePointAnnotation];

BMKAnnotationView* aview = [_mapView viewForAnnotation:imagePointAnnotation];

aview.tag=10000+i;

}

}

然后在- (BMKAnnotationView*)mapView:(BMKMapView*)mapView viewForAnnotation:(id)annotation方法里面來(lái)更改圖片需要顯示的圖片樣式,這里比較簡(jiǎn)單,只需要顯示一張圖片,所以就系統(tǒng)的BMKAnnotationView就可以了,然后設(shè)置圖片,annotationView.image= [UIImageimageNamed:@"你需要顯示的圖片名字"]即可;,這里會(huì)有一個(gè)問題,如果圖片比較小,你在點(diǎn)擊的時(shí)候有可能要點(diǎn)很多次才能準(zhǔn)確點(diǎn)擊到你想要點(diǎn)擊的點(diǎn),這里解決辦法是重寫B(tài)MKAnnotationView的初始化方法,在里面設(shè)置其frame,自定義一個(gè)BMKAnnotationView,然后在.h中添加一個(gè)image,imageview屬性用于顯示你需要的圖片

然后在.m中實(shí)現(xiàn)如下方法,也就是給self添加image。此時(shí)在viewForAnnotation設(shè)置圖片的時(shí)候就需要使用你自定義的屬性annimage來(lái)設(shè)置圖片了annotationView.annimage= [UIImage imageNamed:@"地災(zāi)點(diǎn).png"];

- (id)initWithAnnotation:(id)annotation reuseIdentifier:(NSString*)reuseIdentifier {

if(self= [super initWithAnnotation:annotationreuseIdentifier:reuseIdentifier]) {

[self setBounds:CGRectMake(0.f,0.f,50.f,50.f)];

[self setBackgroundColor:[UIColorclearColor]];

_annotationImageView= [[UIImageViewalloc]initWithFrame:self.bounds];

_annotationImageView.contentMode=UIViewContentModeCenter;

[selfaddSubview:_annotationImageView];

}

returnself;

}

- (void)setAnnimage:(UIImage*)annimage {

_annimage= annimage;

[self updateImageView];

}

- (void)updateImageView {

if([_annotationImageView isAnimating]) {

[_annotationImageView stopAnimating];

}

_annotationImageView.image=_annimage;

_annotationImageView.animationDuration=0.5;

_annotationImageView.animationRepeatCount=0;

[_annotationImageView startAnimating];

}

如何將那個(gè)自定義view也作為標(biāo)注點(diǎn)顯示呢,官方api都只是給出了一個(gè)image屬性供我們?cè)O(shè)置,這里也只能自定義來(lái)處理了,依然是重寫B(tài)MKAnnotationView的初始化方法,在初始化方法中在添加一個(gè)uiview參數(shù),在初始化的時(shí)候?qū)⒛阈枰@示的view傳過去,代碼如下:

- (id)initWithAnnotation:(id)annotation reuseIdentifier:(NSString*)reuseIdentifier customView:(UIView*)detailView {

if(self= [super initWithAnnotation:annotationreuseIdentifier:reuseIdentifier]) {

[self setBounds:CGRectMake(0.f,0.f,142.f,120.f)];

self.backgroundColor= [UIColor clearColor];

self.canShowCallout=NO;

self.centerOffset=CGPointMake(40, -80);//設(shè)置中心點(diǎn)偏移

[self addSubview:detailView];

}

returnself;

}

viewForAnnotation代理方法中代碼如下:

- (BMKAnnotationView*)mapView:(BMKMapView*)mapView viewForAnnotation:(id)annotation {

if(annotation ==imagePointAnnotation) {

NSString*AnnotationViewID =@"imageMark";

ImageAnnoTationView*annotationView = [[ImageAnnoTationView alloc]initWithAnnotation:annotationreuseIdentifier:AnnotationViewID];

//設(shè)置顏色

//annotationView.pinColor = BMKPinAnnotationColorPurple;

//從天上掉下效果

annotationView.annimage= [UIImageimageNamed:@"地災(zāi)點(diǎn).png"];

//annotationView.animatesDrop = YES;

returnannotationView;

}elseif(annotation ==customPointAnnotation) {

[[NSBundlemainBundle]loadNibNamed:@"PredictView"owner:selfoptions:nil];

self.customView.frame=CGRectMake(0,0,142,120);

self.customView.tag=111222333;//設(shè)置一個(gè)tag值方便后面顯示隱藏調(diào)用

CustomAnnotationView*customAnnotationView = [[CustomAnnotationViewalloc]initWithAnnotation:annotationreuseIdentifier:@"CustomID"customView:self.customView];//將你需要自定義的view傳給他自己的初始化方法

returncustomAnnotationView;

}

returnnil;

}

此時(shí)點(diǎn)已經(jīng)在地圖上描出來(lái)了,然后就是點(diǎn)擊這個(gè)標(biāo)注的響應(yīng)事件,百度地圖中有一個(gè)代理類似于tableview的選中某行方法,-(void)mapView:(BMKMapView*)mapView didSelectAnnotationView:(BMKAnnotationView*)view

在這個(gè)方法里將你需要顯示的詳情view加載出來(lái),然后在地圖zoomlevel較小的時(shí)候?qū)⑵湓O(shè)置成當(dāng)前BMKAnnotationView的paopaoview

-(void)mapView:(BMKMapView*)mapView didSelectAnnotationView:(BMKAnnotationView*)view {

if(view.tag>=10000&& view.tag<20000) {

seleView= view;

[[NSBundlemainBundle]loadNibNamed:@"PredictView"owner:selfoptions:nil];

UIView*areaPaoView=[[UIView alloc]initWithFrame:CGRectMake(0,0,242,125)];

self.customView.frame=CGRectMake(90,0,142,120);

[areaPaoView addSubview:self.customView];

BMKActionPaopaoView*paopao=[[BMKActionPaopaoView alloc]initWithCustomView:areaPaoView];

view.paopaoView.hidden=YES;

if(mapView.zoomLevel>ZOOMLEVEL) {

return;

}else{

view.paopaoView= paopao;

}

}elseif(view.tag>=20000&& view.tag<30000) {

if(mapView.zoomLevel

return;

}

[selfpopVC];

}

}

最后就是在mapview的另一個(gè)代理方法中判斷zoomlevel,來(lái)決定是否要顯示自定義view那個(gè)標(biāo)注了

*地圖渲染每一幀畫面過程中,以及每次需要重繪地圖時(shí)(例如添加覆蓋物)都會(huì)調(diào)用此接口

*@param mapView地圖View

*@param status此時(shí)地圖的狀態(tài)

*/

- (void)mapView:(BMKMapView*)mapView onDrawMapFrame:(BMKMapStatus*)status {

NSLog(@"%f",mapView.zoomLevel);

if(mapView.zoomLevel>ZOOMLEVEL) {

if(!isSuccessLocation) {//地圖在定位過程中zoomlevel波動(dòng)較大,所以在定位成功后用isSuccessLocation來(lái)標(biāo)記

for(BMKPointAnnotation*annincustomPointArr) {

BMKAnnotationView* annView = [_mapViewviewForAnnotation:ann];

UIView*view = [annViewviewWithTag:111222333];

[viewsetHidden:NO];

}

//防止在地圖放大之前用戶已經(jīng)選中某個(gè)點(diǎn)了

[mapViewdeselectAnnotation:seleView.annotationanimated:YES];

isSuccessLocation=YES;//避免地圖放大過程中頻繁調(diào)用此方法,所以在zoomlevel大于ZOOMLEVEL后就一直顯示自定義view

}

}else{

if(isSuccessLocation) {

for(BMKPointAnnotation*annincustomPointArr) {

BMKAnnotationView* annView = [_mapView viewForAnnotation:ann];

UIView*view = [annView viewWithTag:111222333];

[viewsetHidden:YES];

}

isSuccessLocation=NO;

}

}

}

到這里重點(diǎn)部分已經(jīng)講的差不多了,第一次寫文章,可能在邏輯上表達(dá)不是很清楚,有不清楚的地方看demo相信能解決你類似的需求的,附上github鏈接 demo下載地址,有什么不足或有什么其他實(shí)現(xiàn)思路的的可以一起交流討論。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.集成地圖環(huán)境 先去百度官方下載SDK,然后導(dǎo)入對(duì)應(yīng)的文件到你的項(xiàng)目中,在這里雜亂的不說,提幾個(gè)地方:mapap...
    博行天下閱讀 1,026評(píng)論 0 1
  • 出自http://my.oschina.net/are1OfBlog/blog/420034 摘要 現(xiàn)在很多社交、...
    JJO閱讀 4,327評(píng)論 4 19
  • http://www.cnblogs.com/kenshincui/p/4125570.html 摘要: 現(xiàn)在很多...
    大崔老師閱讀 3,472評(píng)論 1 2
  • 最近仿照美團(tuán)做了款應(yīng)用,剛好用到百度地圖,高德地圖之前用的比較多,只是這個(gè)項(xiàng)目的后臺(tái)服務(wù)器是另外一個(gè)公司做的,他們...
    奔跑的小螞蟻_8b28閱讀 1,269評(píng)論 0 1
  • 實(shí)現(xiàn)效果: 實(shí)現(xiàn)思路: 一:后臺(tái)獲取每個(gè)區(qū)的數(shù)據(jù) -(void)addAnnotationWithArray:(N...
    歐大帥Allen閱讀 2,165評(píng)論 12 11

友情鏈接更多精彩內(nèi)容