以编程方式更改MKAnnotationView [英] Change MKAnnotationView programmatically

查看:74
本文介绍了以编程方式更改MKAnnotationView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以更改MKAnnotationView样式(例如从带有数字的红色标签更改为带有数字的绿色标签).

Is there a way to change MKAnnotationView style (like from red label with number to green colored label with number).

我想根据距目标的距离更改此样式.我的注释正在与用户一起移动.

I want to change this style according to distance from target. My annotation is moving, with user.

我不想使用删除/添加注释,因为它会引起闪烁". 可以做到吗?

I dont want to use remove / add annotation, because it causes "blinking". Can it be done someway?

更新:

我正在添加代码,我现在是怎么做的

I am adding code, how I am doing it right now

MKAnnotationView *av = [mapView viewForAnnotation:an];

if ([data->type isMemberOfClass:[UserAnnotationImage class]])
{
    UIImage *img = [UIImage imageNamed: ((UserAnnotationImage *)data->type)->url];
    [av setImage:img];
}
else if ([data->type isMemberOfClass:[UserAnnotationLabel class]])
{

    UIView * v = [av viewWithTag:0];
    v = ((UserAnnotationLabel *)data->type)->lbl;

    av.frame = ((UserAnnotationLabel *)data->type)->lbl.frame;
}
else if ([data->type isMemberOfClass:[UserAnnotationView class]])
{

    UIView * v = [av viewWithTag:0];
    v = ((UserAnnotationView *)data->type)->view;
    av.frame = ((UserAnnotationView *)data->type)->view.frame;
}

可悲的是,它不起作用:(

Sadly, its not working :(

推荐答案

是的,基本上,您将获得对注释视图的引用并直接更新其内容.

Yes, basically you get a reference to the annotation view and update its contents directly.

如果您有一个自定义的注释视图类,另一种方法是让注释视图监视它感兴趣的更改(或在外部告诉它)并自我更新.

Another way, if you have a custom annotation view class, is to have the annotation view monitor the changes it is interested in (or have something outside tell it) and update itself.

如果使用普通的MKAnnotationViewMKPinAnnotationView,则第一种方法更简单.

The first approach is simpler if you are using a plain MKAnnotationView or MKPinAnnotationView.

无论何时检测到需要更改视图,都可以通过调用地图视图的viewForAnnotation instance方法来获取对该视图的引用.这与调用viewForAnnotation委托方法不同.

Wherever you detect that a change to the view is needed, get a reference to the view by calling the map view's viewForAnnotation instance method. This is not the same as calling the viewForAnnotation delegate method.

一旦您引用了该视图,就可以根据需要进行修改,并且更改应立即显示.

Once you have a reference to the view, you can modify as needed and the changes should appear immediately.

重要的一点是,您用来更新委托方法之外的视图的逻辑与您在viewForAnnotation委托方法中具有的逻辑必须匹配.这是因为委托方法可能稍后会被地图视图调用(在您手动更新了视图之后),当这样做时,其中的代码应将更新后的数据考虑在内.

An important point is that the logic you use to update the view outside the delegate method and the logic you have in the viewForAnnotation delegate method must match. This is because the delegate method may get called later (after you've updated the view manually) by the map view and when it does, the code there should take the updated data into account.

最好的方法是将注释视图构造代码放在由委托方法调用的通用方法中,并在其中手动更新视图.

The best way to do that is to have the annotation view construction code in a common method called both by the delegate method and where you update the view manually.

有关示例,请参见从MKMapView中的MKAnnotation更改UIImage .仅更新注释视图的image.

See change UIImage from MKAnnotation in the MKMapView for an example that updates just the annotation view's image.

有关使用自定义批注视图类更新视图的示例(主要是一种方法的想法),请参见,该标题会定期更新视图的图钉颜色(绿色,紫色,红色,绿色,紫色,红色,等).

For an example (mostly an idea for an approach) of updating the view using a custom annotation view class, see iPad Mapkit - Change title of "Current Location" which updates the view's pin color periodically (green, purple, red, green, purple, red, etc).


您的代码中有太多未知数,无法解释为什么它不起作用.例如:


There are too many unknowns in your code to explain why it doesn't work. For example:

  • 什么是data?是否特定于注释(与an有关)?什么是type?将注释添加到地图后,它会更改吗?
  • 为什么data存储像UILabelUIView这样的整个视图对象,而不是仅存储要在这些视图中显示的基础数据?
  • imageNamed要求图像必须是项目中的资源(不是任意的URL)
  • 请勿使用0标记(这是所有视图的默认标记).从1开始编号.
  • 您使用viewWithTag获得了一个视图,但是立即将其替换为另一个视图.
  • What is data? Is it annotation-specific (is it related to an)? What is type? Does it change after the annotation has been added to the map?
  • Why is data storing entire view objects like a UILabel or UIView instead of just the underlying data that you want to show in those views?
  • imageNamed requires the image to be a resource in the project (not any arbitrary url)
  • Don't use a tag of 0 (that's the default for all views). Start numbering from 1.
  • You get a view using viewWithTag but then replace it immediately with another view.


相反,我会提供更详细但更简单的示例 ...


I'll instead give a more detailed but simple(r) example...

假设您具有一个带有以下属性(除了坐标,标题和字幕)的注释类(实现MKAnnotation的注释类):

Assume you have an annotation class (the one that implements MKAnnotation) with these properties (in addition to coordinate, title, and subtitle):

@property (nonatomic, assign) BOOL haveImage;
@property (nonatomic, copy) NSString *labelText;
@property (nonatomic, copy) NSString *imageName;
@property (nonatomic, assign) CLLocationDistance distanceFromTarget;

要解决上述重要点"(viewForAnnotation委托方法和view-update-code应该使用相同的逻辑),我们将创建一个传递注释视图并将其配置为的方法根据注释的属性需要.然后,viewForAnnotation委托方法和在注释属性更改时手动更新视图的代码都将调用此方法.

To address the "important point" mentioned above (that the viewForAnnotation delegate method and the view-update-code should use the same logic), we'll create a method that is passed an annotation view and configures it as needed based on the annotation's properties. This method will then be called both by the viewForAnnotation delegate method and the code that manually updates the view when the annotation's properties change.

在此示例中,我做到了,如果haveImageYES,则注释视图将显示图像,否则将显示标签.此外,标签的背景颜色基于distanceFromTarget:

In this example, I made it so that the annotation view shows the image if haveImage is YES otherwise it shows the label. Additionally, the label's background color is based on distanceFromTarget:

-(void)configureAnnotationView:(MKAnnotationView *)av
{
    MyAnnotationClass *myAnn = (MyAnnotationClass *)av.annotation;

    UILabel *labelView = (UILabel *)[av viewWithTag:1];

    if (myAnn.haveImage)
    {
        //show image and remove label...
        av.image = [UIImage imageNamed:myAnn.imageName];
        [labelView removeFromSuperview];
    }
    else
    {
        //remove image and show label...
        av.image = nil;

        if (labelView == nil)
        {
            //create and add label...
            labelView = [[[UILabel alloc] 
                initWithFrame:CGRectMake(0, 0, 50, 30)] autorelease];
            labelView.tag = 1;
            labelView.textColor = [UIColor whiteColor];
            [av addSubview:labelView];
        }

        if (myAnn.distanceFromTarget > 100)
            labelView.backgroundColor = [UIColor redColor];
        else
            labelView.backgroundColor = [UIColor greenColor];

        labelView.text = myAnn.labelText;
    }
}

viewForAnnotation委托方法如下:

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation 
{
    if ([annotation isKindOfClass:[MyAnnotationClass class]])
    {
        static NSString *myAnnId = @"myann";
        MKAnnotationView *av = [mapView dequeueReusableAnnotationViewWithIdentifier:myAnnId];
        if (av == nil)
        {
            av = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:myAnnId] autorelease];
        }
        else
        {
            av.annotation = annotation;
        }

        [self configureAnnotationView:av];

        return av;
    }

    return nil;
}

最后,注释属性发生变化的地方以及您要更新注释视图的地方,代码将如下所示:

Finally, the place where the annotation's properties change and where you want to update the annotation view, the code would look something like this:

ann.coordinate = someNewCoordinate;
ann.distanceFromTarget = theDistanceFromTarget;
ann.labelText = someNewText;
ann.haveImage = YES or NO;
ann.imageName = someImageName;

MKAnnotationView *av = [mapView viewForAnnotation:ann];
[self configureAnnotationView:av];

这篇关于以编程方式更改MKAnnotationView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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