2

我在 MKMapView 上设置了多个注释。我不想在单击图钉时使用地图注释标注,而是希望将子视图 ( self.detailView) 动画化到屏幕底部,并在未选择任何内容时将其移回。当用户选择了一个图钉,然后选择了另一个图钉时,我希望我的视图在屏幕外显示动画,然后立即在屏幕上显示动画(当然,与新选择的注释对应的不同信息)。

没有想太多,我尝试了似乎很容易做的事情 - 选择注释时,self.detailView在屏幕上设置动画,当取消选择时,在屏幕外设置动画self.detailView

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    NSLog( @"selected annotation view" );

    [UIView animateWithDuration:0.2f
                          delay:0.0f
                        options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
                      animations:^{
                          [self.detailView setFrame:CGRectMake(0, 307, 320, 60)];       
                      }
                      completion:^(BOOL finished){                

                      }];
}

- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
    NSLog( @"deselected annotation view" );

    [UIView animateWithDuration:0.2f
                          delay:0.0f
                        options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
                      animations:^{
                          [self.detailView setFrame:CGRectMake(0, 367, 320, 60)];       
                      }
                      completion:^(BOOL finished){

                      }];

}

This works fine when no pin is selected and the user selects a pin, and when a pin is selected and the user deselects it by clicking on empty space. 当然,当一个 pin 已经被选中时,问题就出现了:如果用户随后点击另一个 pin,didDeselectAnnotationViewdidSelectAnnotationView快速连续触发,两个动画会尝试同时运行,结果效果无法正常工作. 通常我会通过将第二个动画放在第一个动画的完成块中来将动画链接在一起,但由于它们是在单独的方法中,我显然不能在这里这样做。

有人对我如何解决这个问题有任何想法吗?谢谢!

4

1 回答 1

2

可能有更好的方法来做你想做的事,但我会先回答你的具体问题。

在你的控制器中实现公共方法来控制动画关闭和再次打开的视图:

- (void)showInfoView:(MyInfoClass*)theInfo;
- (void)hideInfoView;

showInfoView您设置一个显示/显示的标志并在屏幕上对其进行动画处理 - 在一个块中执行此代码并立即调用它只是为了让它像这样工作......

dispatch_block_t showBlock = ^
{
    self.isShowing = YES;
    /* show code goes here */
};
showBlock();

hideInfoView您关闭动画并取消设置动画完成块中的标志。

现在在showInfoView调用之前showBlock检查标志以确保它尚未显示 - 如果是,则不要立即执行块,而是将其添加到被NSMutableArray调用的末尾toShowBlocks。然后在hideInfoView取消设置标志之前检查toShowBlocks数组是否为空,如果不是,则删除并调用第一项(使用数组作为 FIFO 队列),如下所示......

dispatch_block_t nextShowBlock = [toShowBlocks objectAtIndex:0];
[toShowBlocks removeObjectAtIndex:0];
nextShowBlock();

然后,您只需在选择/取消选择引脚时调用您的显示和隐藏方法,这将为您处理。这至少应该让你走上正确的道路。

也许更好的方法:

上面有一些问题,如果用户疯狂地按下图钉,动画视图可能会被隐藏并显示很多,导致在用户获得最后一个动画之前出现冗长的动画队列。此外,当用户平移和缩放地图时,视图不会像注释那样跟随地图。因此,您最好为信息视图使用自定义注释。这是一个真正的痛苦,因为MKAnnotation视图的行为不像常规UIView的 s,这会导致各种问题。MKAnnotation但是,我在此答案中描述了一种将s 用作自定义标注的方法: https ://stackoverflow.com/a/8649951/461492 。

于 2012-11-01T02:09:49.283 回答