如何将UIBezierPath引入MKAnnotation对象的后面? [英] How to bring UIBezierPath to the back of a MKAnnotation object?

查看:75
本文介绍了如何将UIBezierPath引入MKAnnotation对象的后面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用中,用户在地图上绘制一个形状并使用UIBeizerPath我正在绘制该路径。然后基于路径的坐标我显示仅在该区域中的结果。一切都很好,除了现在当Annotations在Map视图中掉落时,引脚看起来像是在路径后面,这意味着路径在前面看起来。

In my app, user draws a shape on map and using UIBeizerPath i am drawing that path. Then based on the coordinates of the path i am displaying the results which are only in that area. Everything works great except that now when Annotations drops on the Map view the pins looks like they are behind the path which means path looks in the front.

我正在使用此代码显示注释和路径:

I am using this code to display the Annotation and path :

 -(void)clearAnnotationAndPath:(id)sender {
    [_mapView removeAnnotations:_mapView.annotations];
    path = [UIBezierPath bezierPath];
    [shapeLayer removeFromSuperlayer];
}

- (void)handleGesture:(UIPanGestureRecognizer *)gesture
{

    CGPoint location = [gesture locationInView:_pathOverlay];

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        shapeLayer = [[CAShapeLayer alloc] init];
        shapeLayer.fillColor = [[UIColor clearColor] CGColor];
        shapeLayer.strokeColor = [[UIColor greenColor] CGColor];
        shapeLayer.lineWidth = 5.0;
        //[_mapView.layer addSublayer:shapeLayer];
        [pathOverlay.layer addSublayer:shapeLayer];
        path = [UIBezierPath bezierPath];
        [path moveToPoint:location];
    }

    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        [path addLineToPoint:location];
        shapeLayer.path = [path CGPath];
    }

    else if (gesture.state == UIGestureRecognizerStateEnded)
    {
        // MKMapView *mapView = (MKMapView *)gesture.view;

        [path addLineToPoint:location];
        [path closePath];
        allStations = [RoadmapData sharedInstance].data;
        for (int i=0; i<[allStations count]; i++) {
            NSDictionary * itemNo = [allStations objectAtIndex:i];

            NSString * fullAddress = [NSString stringWithFormat:@"%@,%@,%@,%@",[itemNo objectForKey:@"address"],[itemNo objectForKey:@"city"],[itemNo objectForKey:@"state"],[itemNo objectForKey:@"zip"]];
            CLGeocoder * geoCoder = [[CLGeocoder alloc]init];
            [geoCoder geocodeAddressString:fullAddress completionHandler:^(NSArray *placemarks, NSError *error) {

                if (error) {
                    NSLog(@"Geocode failed with error: %@", error);
                    return;
                }

                if(placemarks && placemarks.count > 0)
                {
                    CLPlacemark *placemark = placemarks[0];
                    CLLocation *location = placemark.location;
                    CLLocationCoordinate2D coords = location.coordinate;
                    CGPoint loc = [_mapView convertCoordinate:coords toPointToView:_pathOverlay];
                    if ([path containsPoint:loc])
                    {
                        NSString * name = [itemNo objectForKey:@"name"];
                        stationAnn = [[LocationAnnotation alloc]initWithCoordinate:coords Title:name subTitle:@"Wells Fargo Offer" annIndex:i];
                        stationAnn.tag = i;
                        [_mapView addAnnotation:stationAnn];
                    }
                    else{
                        NSLog(@"Out of boundary");
                    }
                }
            }];
            [self turnOffGesture:gesture];
        }
    }
}

- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views{
    if (views.count > 0) {
        UIView* firstAnnotation = [views objectAtIndex:0];
        UIView* parentView = [firstAnnotation superview];
        if (_pathOverlay == nil){
            // create a transparent view to add bezier paths to
            pathOverlay = [[UIView alloc] initWithFrame: parentView.frame];
            pathOverlay.opaque = NO;
            pathOverlay.backgroundColor = [UIColor clearColor];
            [parentView addSubview:pathOverlay];
        }

        // make sure annotations stay above pathOverlay
        for (UIView* view in views) {
            [parentView bringSubviewToFront:view];
        }
    }
}

此外,一旦我从这个和查看再来它甚至没有绘制路径。

Also once i go back from this and view and come again its not even drawing the Path.

请帮助。

谢谢,

推荐答案

显然,当您通过以下方式将贝塞尔曲线路径添加到地图时:

Apparently, when you add your bezier path to the map via:

        [_mapView.layer addSublayer:shapeLayer];

它被添加 某些内部层 MKMapView 用于绘制注释。如果你看一下这个有点相关的问题,你会发现你可以实现 MKMapViewDelegate 协议,并在添加新的电台注释时获得回调。当发生这种情况时,您基本上检查新添加注释的视图层次结构,并在它们下面插入一个新的,透明的 UIView 。您需要注意将所有注释带到此透明 UIView 前面。

it is getting added above some internal layer that MKMapView uses to draw the annotations. If you take a look at this somewhat related question, you'll see that you can implement the MKMapViewDelegate protocol, and get callbacks when new station annotations are added. When this happens, you basically inspect the view heirarchy of the newly added annotations, and insert a new, transparent UIView layer underneath them. You take care to bring all the annotations in front of this transparent UIView.

  // always remember to assign the delegate to get callbacks!
  _mapView.delegate = self;

...

#pragma mark - MKMapViewDelegate

- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views{
    if (views.count > 0) {
        UIView* firstAnnotation = [views objectAtIndex:0];
        UIView* parentView = [firstAnnotation superview];
        // NOTE: could perform this initialization in viewDidLoad, too
        if (self.pathOverlay == nil){
            // create a transparent view to add bezier paths to
            pathOverlay = [[UIView alloc] initWithFrame: parentView.frame];
            pathOverlay.opaque = NO;
            pathOverlay.backgroundColor = [UIColor clearColor];
            [parentView addSubview:pathOverlay]; 
        }

        // make sure annotations stay above pathOverlay
        for (UIView* view in views) {
            [parentView bringSubviewToFront:view];
        }
    }
}

然后,而不是添加你的将图层添加到 _mapView.layer ,将其添加到透明视图图层,也在坐标转换中使用此新图层:

Then, instead of adding your shape layer to _mapView.layer, you add it to your transparent view layer, also using this new layer in the coordinate conversion:

- (void)handleGesture:(UIPanGestureRecognizer*)gesture
{
    CGPoint location = [gesture locationInView: self.pathOverlay];

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        if (!shapeLayer)
        {
            shapeLayer = [[CAShapeLayer alloc] init];
            shapeLayer.fillColor = [[UIColor clearColor] CGColor];
            shapeLayer.strokeColor = [[UIColor greenColor] CGColor];
            shapeLayer.lineWidth = 5.0;
            [pathOverlay.layer addSublayer:shapeLayer];   // <- change here !!!
        }
        self.path = [[UIBezierPath alloc] init];
        [path moveToPoint:location];
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        [path addLineToPoint:location];
        shapeLayer.path = [path CGPath];
    }
    else if (gesture.state == UIGestureRecognizerStateEnded)
    {
        /*
         * This code is the same as what you already have ...
         */

             // But replace this next line with the following line ...
             //CGPoint loc = [_mapView convertCoordinate:coords toPointToView:self];
             CGPoint loc = [_mapView convertCoordinate:coords toPointToView: self.pathOverlay];

        /*
         * And again use the rest of your original code
         */            
    }
}

我还为新的透明层添加了 ivar (和属性):

where I also added an ivar (and property) for the new transparent layer:

UIView* pathOverlay;

我用一个虚假的站点网格对此进行了测试,得到了以下结果:

I tested this with a bogus grid of stations and got the following results:

PS我还建议摆脱你的静态变量。只要让它们成为你班级的ivars /属性。

P.S. I'd also recommend getting rid of your static variables. Just make them ivars/properties of your class.

这篇关于如何将UIBezierPath引入MKAnnotation对象的后面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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