我有一个可能绘制了数百个多边形的MKMapView。假设在iOS7上使用MKPolygon和MKPolygonRenderer作为之一。
我需要的是一种对用户触摸多边形之一起作用的方法。例如,它们代表 map 上具有一定人口密度的区域。
在iOS6上,MKOverlays被绘制为MKOverlayViews,因此触摸检测更加简单。现在使用渲染器,我真的不知道该如何完成。
我不确定这是否会有所帮助,甚至是否相关,但作为引用,我将发布一些代码:
这将使用mapData将所有MKOverlays添加到MKMapView。
-(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的委托(delegate)方法:
-(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,将点击的点转换为 map 坐标,浏览我的叠加层并使用CGPathContainsPoint进行检查。
添加TapGestureRecognizer。我做了增加第二个双击手势的技巧,以便在双击 map 时不会触发单击手势。如果有人知道更好的方法,我很高兴听到!
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
然后,在点击处理程序上:
-(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);
}
}
}
我可以要求已经具有“path”属性的MKPolygonRenderer并使用它,但是由于某些原因,它始终为nil。我确实读过别人的话,说我可以在渲染器上调用invalidatePath,它确实填充了path属性,但由于在任何多边形内都找不到该点,因此这似乎是错误的。这就是为什么我要从各个角度重建路径。这样,我什至不需要渲染器,而只使用MKPolygon对象。
关于ios - 在iOS7中检测MKOverlay的触摸(MKOverlayRenderer),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20858108/