2011-12-12 48 views
2

如何检测注释标注的标题的点击?我已经有了一个正确的标注配件和一个左侧标签,但是我想要检测用户是否点击标题(位于标注的中心)。检测标注的标注

如果这是不可能的,如果我点击标题,如何禁用隐藏标注?

回答

4

回答你的问题有点晚,但我最近处理的是同样的问题,并通过我自己的试验和错误来解决我的问题。也许我可以帮助处理同样问题的人。

你也可以使用一些自定义注释和标注视图类,这里有很多例子。 但是,还有一种简单的方法可以在不使用复杂的外部类的情况下解决这个问题。

问题定义: 我希望能够通过触摸标注视图来触发某些方法。 我不想使用右侧或左侧的配件按钮。 但是当我触摸标注视图时,视图将立即消失。

解决方案的简短说明: 只需使用自定义的“MKPinAnnotationView”和“hittest”来检测标注视图中的触摸。

你也可以在帖子末尾找到github项目链接。

touchableCallOutsViewController.h

// 
// touchableCallOutsViewController.h 
// touchableCallOuts 
// 
// Created by yasin turkoglu on 20.11.2012. 
// Copyright (c) 2012 yasin turkoglu. All rights reserved. 
// 

#import <UIKit/UIKit.h> 
#import <MapKit/MapKit.h> 


@class myCustomPinAnnotationClass; 

@interface touchableCallOutsViewController : UIViewController <MKMapViewDelegate> { 
    MKMapView *myMapView; 
    int pinCounter; 
    myCustomPinAnnotationClass *myAnnotation; 
    CLLocationCoordinate2D selectedPinCoordinate; 
    int selectedPinNumber; 
} 

@property (strong, nonatomic) MKMapView *myMapView; 
@property (strong, nonatomic) myCustomPinAnnotationClass *myAnnotation; 
@end 

touchableCallOutsViewController.m

// 
// touchableCallOutsViewController.m 
// touchableCallOuts 
// 
// Created by yasin turkoglu on 20.11.2012. 
// Copyright (c) 2012 yasin turkoglu. All rights reserved. 
// 

#import "touchableCallOutsViewController.h" 
#import "myCustomPinAnnotationClass.h" 

@interface touchableCallOutsViewController() 

@end 



@implementation touchableCallOutsViewController 

@synthesize myMapView; 
@synthesize myAnnotation; 

- (void)viewDidLoad 
{ 

    //first we create mapview and add pin annotation 

    myMapView = [[MKMapView alloc]initWithFrame:self.view.frame]; 
    myMapView.delegate = self; 
    MKCoordinateRegion region = {{0,0},{1.0,1.0}}; 
    region.center.latitude = 41.036651; //user defined 
    region.center.longitude = 28.983870;//user defined 
    [myMapView setRegion:region animated:YES]; 
    [self.view addSubview:myMapView]; 

    //we define long press recognizer for 2 seconds and add our map view to add new pin when you press 2 seconds on map view 
    UILongPressGestureRecognizer *lngPrs = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleMyLongPress:)]; 
    lngPrs.minimumPressDuration = 2.0; 
    [myMapView addGestureRecognizer:lngPrs]; 

    pinCounter = 1; //this variable hold pin numbers and increment 1 when new pin added. 

    myAnnotation = [[myCustomPinAnnotationClass alloc]initWithName:[NSString stringWithFormat:@"Pin %i",pinCounter] description:@"touch here to see pin coordinates" pinNum:pinCounter coordinate:region.center]; 
    [myMapView addAnnotation:myAnnotation]; 

} 

- (void)handleMyLongPress:(UIGestureRecognizer *)gestureRecognizer 
{ 
    if (gestureRecognizer.state != UIGestureRecognizerStateBegan) { 

    }else{ 
     //when we press more than 2 seconds on map view UILongPressGestureRecognizer triggered this method and call our custom MKPinAnnotationView class and add annotation. 
     CGPoint touchPoint = [gestureRecognizer locationInView:myMapView]; 
     CLLocationCoordinate2D touchMapCoordinate = [myMapView convertPoint:touchPoint toCoordinateFromView:myMapView]; 
     pinCounter++; 
     myAnnotation = [[myCustomPinAnnotationClass alloc]initWithName:[NSString stringWithFormat:@"Pin %i",pinCounter] description:@"touch here to see pin coordinates" pinNum:pinCounter coordinate:touchMapCoordinate]; 
     [myMapView addAnnotation:myAnnotation]; 
    } 
} 

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation 
{ 
    //when new annotation added by us, new annotation property will set here 
    static NSString *identifier = @"myPins"; 
    if ([annotation isKindOfClass:[myCustomPinAnnotationClass class]]) { 
     myCustomPinAnnotationClass *annotationView = (myCustomPinAnnotationClass *) [self.myMapView dequeueReusableAnnotationViewWithIdentifier:identifier]; 

     if (annotationView == nil) { 
      annotationView = [[myCustomPinAnnotationClass alloc] initWithAnnotation:annotation reuseIdentifier:identifier]; 
     } else { 
      annotationView.annotation = annotation; 
     } 

     myAnnotation = (myCustomPinAnnotationClass *)annotation; 

     annotationView.pinColor = MKPinAnnotationColorGreen;  
     annotationView.enabled = YES; 
     annotationView.draggable = YES; 
     annotationView.canShowCallout = YES; 
     [annotationView setSelected:YES animated:YES]; 
     return annotationView; 

    }  
    return nil; 

} 

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view 
{ 

    //if you select any annotation to show their callout sellected annotation pin number and coordinate setted and call findcallot method  
    myAnnotation = (myCustomPinAnnotationClass *)view.annotation; 
    selectedPinCoordinate = myAnnotation.coordinate; 
    selectedPinNumber = myAnnotation.pinNum; 
    [self findCallOut:myMapView]; 
} 


- (void)findCallOut:(UIView *)node 
{ 
    //this method dig our mapview with for loop until find callout view class named "UICalloutView" 

    if([node isKindOfClass:[NSClassFromString(@"UICalloutView") class]]){ 

     //this method trigered together with callout open animation. 

     //in UICalloutView we have callout bubble image 
     //we dig it with for loop to find this image height 
     float buubleHeight = 0.0; 
     for(UIImageView *bubbleComponents in node.subviews){ 
      //when we find callout bubble image take height to set our touchable area height 
      buubleHeight = bubbleComponents.frame.size.height; 
      break; 
     } 



     //this method triger with callout open animation as I said before 
     //ant this bouncing open animation distort actual size of callout view 
     //so when this happens we also get transform value of callout view and make proportion to find exact sizes. 
     CGFloat nodeTransformRatio = node.transform.a; 
     CGFloat calculatedWidth = roundf(node.frame.size.width/nodeTransformRatio); 
     CGFloat calculatedHeight = roundf(buubleHeight/nodeTransformRatio); 

     //now create a new UIView and sized according to callout view. 
     UIView *touchableView = [[UIView alloc]initWithFrame:CGRectMake(0.0, 0.0, calculatedWidth, calculatedHeight)]; 
     touchableView.userInteractionEnabled = YES; 

     //we add new single tap gesture recognizer to triger desired method when users touching to the callout 
     UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSomething)]; 
     [touchableView addGestureRecognizer:singleTap]; 
     //and finaly we add this newly created view in callout view to receive touches. 
     [node addSubview:touchableView]; 

    }else{ 
     //loop self until find a "UICalloutView" 
     for(UIView *child in node.subviews){ 
      [self findCallOut:child]; 
     } 
    } 
} 

- (void)doSomething 
{ 
    //this method call allert view our preseted variables when users touch callout view. 
    UIAlertView *alertHolder = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"You're touched the Pin %i CallOut",selectedPinNumber] message:[NSString stringWithFormat:@"lat : %f\nlong : %f",selectedPinCoordinate.latitude,selectedPinCoordinate.longitude] delegate:self cancelButtonTitle:nil otherButtonTitles:@"ok",nil]; 
    [alertHolder show]; 

} 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

@end 

myCustomPinAnnotationClass.h

// 
// myCustomPinAnnotationClass.h 
// touchableCallOuts 
// 
// Created by yasin turkoglu on 20.11.2012. 
// Copyright (c) 2012 yasin turkoglu. All rights reserved. 
// 

#import <MapKit/MapKit.h> 


@interface myCustomPinAnnotationClass : MKPinAnnotationView <MKAnnotation> { 
    NSString *_name; 
    NSString *_description; 
    int _pinNum; 
    CLLocationCoordinate2D _coordinate; 
} 

@property (copy) NSString *name; 
@property (copy) NSString *description; 
@property (nonatomic, readonly) int pinNum; 
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate; 

- (id)initWithName:(NSString*)header description:(NSString*)description pinNum:(int)pinNum coordinate:(CLLocationCoordinate2D)coordinate; 

@end 

myCustomPinAnnotationClass.m

// 
// myCustomPinAnnotationClass.m 
// touchableCallOuts 
// 
// Created by yasin turkoglu on 20.11.2012. 
// Copyright (c) 2012 yasin turkoglu. All rights reserved. 
// 

#import "myCustomPinAnnotationClass.h" 

@implementation myCustomPinAnnotationClass 

@synthesize name = _name; 
@synthesize description = _description; 
@synthesize pinNum = _pinNum; 
@synthesize coordinate = _coordinate; 


- (id)initWithName:(NSString*)header description:(NSString*)description pinNum:(int)pinNum coordinate:(CLLocationCoordinate2D)coordinate 
{ 
    self = [super init]; 
    if (self) { 
     _name = [header copy]; 
     _description = [description copy]; 
     _pinNum = pinNum; 
     _coordinate = coordinate; 
    } 
    return self; 
} 

- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate 
{ 
    _coordinate = newCoordinate; 
} 

- (NSString *)title { 
    return _name; 
} 

- (NSString *)subtitle { 
    return _description; 
} 

- (int)tag { 
    return _pinNum; 
} 

-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    //test touched point in map view 
    //when hit test return nil callout close immediately by default 
    UIView* hitView = [super hitTest:point withEvent:event]; 
    // if hittest return nil test touch point 
    if (hitView == nil){ 
     //dig view to find custom touchable view lately added by us 
     for(UIView *firstView in self.subviews){ 
      if([firstView isKindOfClass:[NSClassFromString(@"UICalloutView") class]]){ 
       for(UIView *touchableView in firstView.subviews){ 
        if([touchableView isKindOfClass:[UIView class]]){ //this is our touchable view class 
         //define touchable area 
         CGRect touchableArea = CGRectMake(firstView.frame.origin.x, firstView.frame.origin.y, touchableView.frame.size.width, touchableView.frame.size.height); 
         //test touch point if in touchable area 
         if (CGRectContainsPoint(touchableArea, point)){ 
          //if touch point is in touchable area return touchable view as a touched view 
          hitView = touchableView; 
         } 
        } 
       }     
      } 
     } 
    } 
    return hitView; 
} 

@end 

在这里,您可以下载完整的项目源代码https://github.com/ytur/touchableCallOutsForIOSMaps

+0

你好@ytur我有同样的问题,我的自定义详图索引视图上市。我已经实现了'hitTest:withEvent:',但'[super hitTest:withEvent:]'永远不会返回'nil'。当我点击标注视图时 - 它消失了,但是当我点击标注视图上的按钮时 - 它没有。有任何想法吗? – k06a

+0

这里是我的完整问题:http://stackoverflow.com/questions/17449775/custom-map-callout-view-hides-on-tap – k06a