在iOS7中检测MKOverlay上的触摸(MKOverlayRenderer) [英] Detecting touches on MKOverlay in iOS7 (MKOverlayRenderer)

查看:126
本文介绍了在iOS7中检测MKOverlay上的触摸(MKOverlayRenderer)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可能有数百个多边形的MKMapView。在iOS7上假设使用MKPolygon和MKPolygonRenderer。

I have an MKMapView with possibly hundreds of polygons drawn. Using MKPolygon and MKPolygonRenderer as one is suppose to on iOS7.

我需要的是一种对用户触摸其中一个多边形的方式。它们代表地图上具有特定人口密度的区域。
在iOS6上,MKOverlay被绘制为MKOverlayViews,因此触摸检测更直接。现在使用渲染器,我真的不知道这是怎么做的。

What I need is a way of acting upon the user touching one of the polygons. They represent an area on the map with a certain population density for example. On iOS6 the MKOverlays were drawn as MKOverlayViews so touch detection was more straightforward. Now using renderers I don't really see how this is suppose to be done.

我不确定这会有所帮助,甚至是否相关,但作为参考我'发布一些代码:

I'm not sure this will help or is even relevant but as a reference I'll post some code:

这会使用mapData将所有MKOverlay添加到MKMapView。

This adds all the MKOverlays to the MKMapView using mapData.

-(void)drawPolygons{
    self.polygonsInfo = [NSMutableDictionary dictionary];
    NSArray *polygons = [self.mapData valueForKeyPath:@"polygons"];

    for(NSDictionary *polygonInfo in polygons){
        NSArray *polygonPoints = [polygonInfo objectForKey:@"boundary"];
        int numberOfPoints = [polygonPoints count];

        CLLocationCoordinate2D *coordinates = malloc(numberOfPoints * sizeof(CLLocationCoordinate2D));
        for (int i = 0; i < numberOfPoints; i++){
            NSDictionary *pointInfo = [polygonPoints objectAtIndex:i];

            CLLocationCoordinate2D point;
            point.latitude = [[pointInfo objectForKey:@"lat"] floatValue];
            point.longitude = [[pointInfo objectForKey:@"long"] floatValue];

            coordinates[i] = point;
        }

        MKPolygon *polygon = [MKPolygon polygonWithCoordinates:coordinates count:numberOfPoints];
        polygon.title = [polygonInfo objectForKey:@"name"];
        free(coordinates);
        [self.mapView addOverlay:polygon];
        [self.polygonsInfo setObject:polygonInfo forKey:polygon.title]; // Saving this element information, indexed by title, for later use on mapview delegate method
    }
}

然后有一个委托方法为每个MKOverlay返回一个MKOverlayRenderer:

Then there is the delegate method for returning a MKOverlayRenderer for each MKOverlay:

-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
    /* ... */

    MKPolygon *polygon = (MKPolygon*) overlay;
    NSDictionary *polygonInfo = [self.polygonsInfo objectForKey:polygon.title]; // Retrieving element info by element title
    NSDictionary *colorInfo = [polygonInfo objectForKey:@"color"];

    MKPolygonRenderer *polygonRenderer = [[MKPolygonRenderer alloc] initWithPolygon:polygon];

    polygonRenderer.fillColor = [UIColor colorWithRed:[[colorInfo objectForKey:@"red"] floatValue]
                                               green:[[colorInfo objectForKey:@"green"] floatValue]
                                                blue:[[colorInfo objectForKey:@"blue"] floatValue]
                                               alpha:[[polygonInfo objectForKey:@"opacity"] floatValue]];

    return polygonRenderer;

    /* ... */
}


推荐答案

我已经完成了。

感谢 incanus Anna

基本上我将一个TapGestureRecognizer添加到MapView,将点击的点转换为地图坐标,浏览我的叠加层并使用CGPathContainsPoint进行检查。

Basically I add a TapGestureRecognizer to the MapView, convert the point tapped to map coordinates, go through my overlays and check with CGPathContainsPoint.

添加TapGestureRecognizer。我做了添加第二个双击手势的技巧,这样当双击缩放地图时,不会触发单击手势。如果有人知道更好的方式,我很高兴听到!

Adding TapGestureRecognizer. I did that trick of adding a second double tap gesture, so that the single tap gesture isn't fired when doing a double tap to zoom on map. If anyone knows a better way, I'm glad to hear!

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapTap:)];
tap.cancelsTouchesInView = NO;
tap.numberOfTapsRequired = 1;

UITapGestureRecognizer *tap2 = [[UITapGestureRecognizer alloc] init];
tap2.cancelsTouchesInView = NO;
tap2.numberOfTapsRequired = 2;

[self.mapView addGestureRecognizer:tap2];
[self.mapView addGestureRecognizer:tap];
[tap requireGestureRecognizerToFail:tap2]; // Ignore single tap if the user actually double taps

然后,在点击处理程序上:

Then, on the tap handler:

-(void)handleMapTap:(UIGestureRecognizer*)tap{
    CGPoint tapPoint = [tap locationInView:self.mapView];

    CLLocationCoordinate2D tapCoord = [self.mapView convertPoint:tapPoint toCoordinateFromView:self.mapView];
    MKMapPoint mapPoint = MKMapPointForCoordinate(tapCoord);
    CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);

    for (id<MKOverlay> overlay in self.mapView.overlays) {
        if([overlay isKindOfClass:[MKPolygon class]]){
            MKPolygon *polygon = (MKPolygon*) overlay;

            CGMutablePathRef mpr = CGPathCreateMutable();

            MKMapPoint *polygonPoints = polygon.points;

            for (int p=0; p < polygon.pointCount; p++){
                MKMapPoint mp = polygonPoints[p];
                if (p == 0)
                    CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
                else
                    CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
            }

            if(CGPathContainsPoint(mpr , NULL, mapPointAsCGP, FALSE)){
                // ... found it!
            }

            CGPathRelease(mpr);
        }
    }
}

我可以要求MKPolygonRenderer已经具有路径属性并使用它,但由于某种原因它始终为零。我确实读过有人说我可以在渲染器上调用invalidatePath并且它确实填充了path属性,但它似乎是错误的,因为在任何多边形中都找不到该点。这就是我从点重建路径的原因。这样我甚至不需要渲染器,只需使用MKPolygon对象。

I could ask for the MKPolygonRenderer which already has the "path" property and use it, but for some reason it is always nil. I did read someone saying that I could call invalidatePath on the renderer and it does fill the path property but it just seems wrong as the point is never found inside any of the polygons. That is why I rebuild the path from the points. This way I don't even need the renderer and just make use of the MKPolygon object.

这篇关于在iOS7中检测MKOverlay上的触摸(MKOverlayRenderer)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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