检测标注标题上的点击 [英] Detect tap on title of callout

查看:137
本文介绍了检测标注标题上的点击的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何检测注释标注的标题上的点按?我已经有一个正确的标注附件和一个左边的附件,但我想检测用户是否点击标题(它在标注的中心)。

how do I detect a tap on the title of a callout of a annotation? I already have a right callout accessory and a left one, but I want to detect if a user taps on the title (which is in the center on the callout).

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

If this is not possible, how do I disable hiding the callout if I tap on the title?

推荐答案

回答你的问题,但我最近处理相同的问题,并使我的解决方案,我的自我尝试和错误。
也许我可以帮助处理相同问题的人。

it's little late to the answer your question but I'm dealing with same kind of problem recently and make my solution by my self with trial and error. maybe I can help someone who dealing with same problem.

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

you can also use some custom annotation and callout view classes, there are many example out there. but, there is a another simple way to solve this problem without use the complex foreign classes.

问题定义:
我想要能只需在标注视图中触摸即可触发某些方法。
我不想使用right或left accesory按钮。
但是当我触摸callout视图时,视图将立即消失。

problem definition: I want to be able to trigger some method just by touching in callout view. I don't want to use right or left accesory buttons. but when I touched callout view, view will disapear immediately.

解决方案的简短解释:
只需使用自定义MKPinAnnotationView 以检测调用视图中的触摸。

short explanation of solution: simply we use custom "MKPinAnnotationView" with "hittest" to detect touches in callout view.

您还可以在帖子末尾找到github项目链接。

you can also find github project link at the end of the post.

touchableCallOutsViewController.h

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

//
//  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

//
//  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

//
//  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 的列表

这篇关于检测标注标题上的点击的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆