MKUserLocation 自定义视图不动!

发布于 2024-11-02 19:31:57 字数 2053 浏览 1 评论 0原文

我为用户位置创建了一个自定义 MKAnnotationView:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation

{

if ([annotation isKindOfClass:[MKUserLocation class]]) {

    if (navStatus == NavStatusHeadingEnabled) {

        if ([annotation isKindOfClass:[MKUserLocation class]]) {

            locationView = [[CustomLocationView alloc] initWithAnnotation:annotation reuseIdentifier:@"locationIdentifier"];
            return locationView;

        }

    }

    return nil;

}

CustomLocationView.h

       - (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
    {
        self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
        if (self != nil)
        {


            self.backgroundColor = [UIColor clearColor];
            blueDot = [UIImage imageNamed:@"userLocationDot.png"].CGImage;
            CGImageRetain(blueDot);

            CGPoint blueDotCenter = CGPointMake((self.frame.size.width - (CGImageGetWidth(blueDot) / 2)) / 2, (self.frame.size.height - (CGImageGetHeight(blueDot) / 2)) / 2);

            blueDotLayer = [CALayer layer];
            blueDotLayer.frame = CGRectMake(blueDotCenter.x, blueDotCenter.y , CGImageGetWidth(blueDot) / 2, CGImageGetHeight(blueDot) / 2);
            blueDotLayer.contents = (id)blueDot;
            blueDotLayer.shadowOpacity = 0.4;
            blueDotLayer.shadowColor = [UIColor blackColor].CGColor;
            blueDotLayer.shadowOffset = CGSizeMake(0.4, 0.3);
            blueDotLayer.shadowRadius = 1.0f;

            [self.layer insertSublayer:blueDotLayer above:self.layer];

        }

        return self;
    }

- (void)setAnnotation:(id <MKAnnotation>)annotation
{
    [super setAnnotation:annotation];

    [self setNeedsDisplay];
}





- (void)dealloc {

    [blueDotLayer release];


    [super dealloc];
}

问题是它只是停留在同一个位置,而不是像蓝点一样移动。 我做错了什么?

谢谢 账单。

I have created a custom MKAnnotationView for User Location:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation

{

if ([annotation isKindOfClass:[MKUserLocation class]]) {

    if (navStatus == NavStatusHeadingEnabled) {

        if ([annotation isKindOfClass:[MKUserLocation class]]) {

            locationView = [[CustomLocationView alloc] initWithAnnotation:annotation reuseIdentifier:@"locationIdentifier"];
            return locationView;

        }

    }

    return nil;

}

CustomLocationView.h

       - (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
    {
        self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
        if (self != nil)
        {


            self.backgroundColor = [UIColor clearColor];
            blueDot = [UIImage imageNamed:@"userLocationDot.png"].CGImage;
            CGImageRetain(blueDot);

            CGPoint blueDotCenter = CGPointMake((self.frame.size.width - (CGImageGetWidth(blueDot) / 2)) / 2, (self.frame.size.height - (CGImageGetHeight(blueDot) / 2)) / 2);

            blueDotLayer = [CALayer layer];
            blueDotLayer.frame = CGRectMake(blueDotCenter.x, blueDotCenter.y , CGImageGetWidth(blueDot) / 2, CGImageGetHeight(blueDot) / 2);
            blueDotLayer.contents = (id)blueDot;
            blueDotLayer.shadowOpacity = 0.4;
            blueDotLayer.shadowColor = [UIColor blackColor].CGColor;
            blueDotLayer.shadowOffset = CGSizeMake(0.4, 0.3);
            blueDotLayer.shadowRadius = 1.0f;

            [self.layer insertSublayer:blueDotLayer above:self.layer];

        }

        return self;
    }

- (void)setAnnotation:(id <MKAnnotation>)annotation
{
    [super setAnnotation:annotation];

    [self setNeedsDisplay];
}





- (void)dealloc {

    [blueDotLayer release];


    [super dealloc];
}

The problem is it just stays on the same place and not moving like the blue dot.
What I am doing wrong?

Thanks
Bill.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

禾厶谷欠 2024-11-09 19:31:57

我刚才也遇到了这个问题。我不确定这是否是预期的行为,但无论出于何种原因,我们都需要移动自定义 MKUserLocation 注释视图。

一个幼稚的解决方案是

- (void) locationController: (LocationController *) locationController
        didUpdateToLocation: (CLLocation *) location
{
    [[self mapView] setShowsUserLocation:NO];

    [[self mapView] setShowsUserLocation:YES];
}

但这会使当前位置注释在屏幕上跳转,我发现这是不可取的。

更好的方法是在视图控制器中保留对自定义注释视图的引用作为 ivar,然后执行以下操作:

- (void) locationController: (LocationController *) locationController
        didUpdateToLocation: (CLLocation *) location
{
    CGPoint newCenterPoint = [[self mapView] convertCoordinate:[location coordinate] toPointToView:[[self customAnnotationView] superview]];
    newCenterPoint.x += [[self customAnnotationView] centerOffset].x;
    newCenterPoint.y += [[self customAnnotationView] centerOffset].y;

    [UIView animateWithDuration:0.3f animations:^{
        [[self customAnnotationView] setCenter:newCenterPoint];
    }];

}

这很好,除非您更改缩放级别时注释保持在相对于地图视图的矩形的位置,然后动画到仅在缩放或平移完成后才能正确定位。最好效仿苹果的做法,让当前位置注释在区域更改期间消失并重新出现:

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    [[self mapView] setShowsUserLocation:NO];
}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    [[self mapView] setShowsUserLocation:YES];
}

I ran into this problem just now as well. I'm not sure if this is expected behavior or not, but for whatever reason it is up to us to move our custom MKUserLocation annotation views.

A naive solution is

- (void) locationController: (LocationController *) locationController
        didUpdateToLocation: (CLLocation *) location
{
    [[self mapView] setShowsUserLocation:NO];

    [[self mapView] setShowsUserLocation:YES];
}

But this makes the current location annotation jump around the screen which I found undesirable.

Better yet is to keep a reference to the custom annotation view as an ivar in your view controller and then do:

- (void) locationController: (LocationController *) locationController
        didUpdateToLocation: (CLLocation *) location
{
    CGPoint newCenterPoint = [[self mapView] convertCoordinate:[location coordinate] toPointToView:[[self customAnnotationView] superview]];
    newCenterPoint.x += [[self customAnnotationView] centerOffset].x;
    newCenterPoint.y += [[self customAnnotationView] centerOffset].y;

    [UIView animateWithDuration:0.3f animations:^{
        [[self customAnnotationView] setCenter:newCenterPoint];
    }];

}

This is good except when you change the zoom level the annotation stays where it was relative to the map view's rect and then animates to the correct location only after the zoom or pan is complete. Best to follow Apple's lead and make the current location annotation disappear and reappear during region changes:

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    [[self mapView] setShowsUserLocation:NO];
}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    [[self mapView] setShowsUserLocation:YES];
}
向日葵 2024-11-09 19:31:57

Bill,

您需要一个已使用适用的desiredAccuracy 和distanceFilter 进行初始化的CLLocationManager,然后实现适用的委托方法,并将您自己的代码设置为locationManager 实例上的委托。

至少,您应该具有以下方法,位置管理器在确定所需精度中的当前位置后将调用该方法,然后每当满足 distanceFilter 时再次调用该方法。

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation ;

干杯,
马克

Bill,

You need a CLLocationManager that has been initialized with an applicable desiredAccuracy and distanceFilter and then implement the applicable delegate methods, and set your own code as the delegate on the locationManager instance.

At a minimum you should have the following method which the Location Manager will call once it has determined the current location with in the desiredAccuracy and then again whenever the distanceFilter has been met.

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation ;

Cheers,
Mack

予囚 2024-11-09 19:31:57

我刚刚找到了这个问题的答案。我的代码是在 Monotouch 中,但在 ObjC 中重新做同样的事情应该很容易。
要在默认 MKUserLocation 上显示自定义图像,我们需要在原始视图之上添加一个子视图。为此,请覆盖 MKMapView 委托中的 DidAddAnnotationViews

void DidAddAnnotationViews (object sender, MKMapViewAnnotationEventArgs e)
{
            MKAnnotationView v = mapView.ViewForAnnotation(mapView.UserLocation);
            if(v != null)
            {
                if(v.Subviews.Count() == 0)
                {
                    UIImageView iv = new UIImageView(new RectangleF(0,0, 22, 22));
                    iv.Image = UIImage.FromFile("res/pins/Yhere.png");
                    v.AddSubview(iv);
                    v.BringSubviewToFront(iv);
                }
            }
}

这使得自定义图像在蓝点顶部移动。此外,用户跟踪和位置更新功能运行良好,您仍然可以看到指示位置准确性的蓝色圆圈。

享受自定义 MKUserLocation 的乐趣!

I just found an answer for this problem. My code is in Monotouch, but it should be easy to re-do the same in ObjC.
to show customized image over default MKUserLocation we need to add a subview on top of the original one. to do this, override DidAddAnnotationViews in MKMapView delegate

void DidAddAnnotationViews (object sender, MKMapViewAnnotationEventArgs e)
{
            MKAnnotationView v = mapView.ViewForAnnotation(mapView.UserLocation);
            if(v != null)
            {
                if(v.Subviews.Count() == 0)
                {
                    UIImageView iv = new UIImageView(new RectangleF(0,0, 22, 22));
                    iv.Image = UIImage.FromFile("res/pins/Yhere.png");
                    v.AddSubview(iv);
                    v.BringSubviewToFront(iv);
                }
            }
}

This gives custom image moving on top of blue dot. more over, user tracking and location updates features works perfectly and you still can see blue circles that indicate location accuracy.

Have fun customizing MKUserLocation!

吝吻 2024-11-09 19:31:57

这是苹果开发者技术支持的答案

我刚刚与 MapKit 工程师交谈完毕,他们确认这是 iOS 中的一个错误。
我的测试应用程序也遇到了同样的问题。

我不知道 iOS 6 是否修复了这个问题,答案是 iOS 5。

Here is the answer from Apple Developer Technical Support

I just finished talking to the MapKit engineers and they confirmed that this is a bug in iOS.
My test app is experiencing the same problem.

I don't know if this was fixed in iOS 6, the answer is for the iOS 5.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文