UIView阻止动画不从当前状态开始

时间:2014-03-27 05:39:04

标签: ios objective-c animation uiview uiviewanimation

我正在尝试为注释视图的子视图设置一些子视图。

因此,为了更清楚,灰色图钉是我的注释视图,它有一个不可见的子视图,这个子视图包含这4个彩色圆视图。

annotation view
 | invisible view (called typeSelectionView)
    | yellow view (called typeButton)
    | blue view (called typeButton)
    | green view (called typeButton)
    | red view (called typeButton)

enter image description here

首先圆圈不可见(变换比例(0,0)及其中心位于灰色针脚的头部),然后,当我选择灰色针脚时,这些圆圈来自针头生长并移动到它们的原始位置(上图中的那个)。

当我取消选择该引脚时,会发生相反的动画。 当我在动画完成之前选择并取消选择(或相反)时,它会改变它的运行方式(如果它正在增长它会收缩)在中间恢复动画。这就是我需要UIViewAnimationOptionBeginFromCurrentState

的原因
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)annotationView
{
    // in case the typeSelectionView was already being showed by another annotationView
    if (self.typeSelectionView.superview != annotationView) {
        [self.typeSelectionView removeFromSuperview];
        [self.typeSelectionView showTypeButtons:NO animated:NO completion:NULL];
    }

    [annotationView addSubview:self.typeSelectionView];
    [self.typeSelectionView showTypeButtons:YES animated:YES completion:NULL];
}

- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)annotationView
{
    if (self.typeSelectionView.superview) {
        [self.typeSelectionView showTypeButtons:NO
                                       animated:YES
                                     completion:^(BOOL finished) {
                                         if (finished) {
                                             [self.typeSelectionView removeFromSuperview];
                                         }
                                     }];
    }
}

- (void)showTypeButtons:(BOOL)show animated:(BOOL)animated completion:(void (^)(BOOL))completion
{
    void (^block)(void) = ^{
        for (int i = 0; i < self.typeButtons.count; i++) {
            TypeButton *typeButton = self.typeButtons[i];

            if (show) {
                typeButton.center = [self _typeButtonCenterForIndex:i numberOfButtons:self.typeButtons.count];
                typeButton.transform = CGAffineTransformIdentity;
            } else {
                typeButton.center = CGPointMake(viewWidth / 2, viewheight + 5); // pin head center
                typeButton.transform = CGAffineTransformMakeScale(0, 0);
            }
        }
    };

    if (animated) {
        [UIView animateWithDuration:0.5
                              delay:0
                            options:UIViewAnimationOptionBeginFromCurrentState
                         animations:block
                         completion:^(BOOL finished) {
                             if (completion) {
                                 completion(finished);
                             }
                         }];
    } else {
        block();

        if (completion) {
            completion(YES);
        }
    }
}

到目前为止没问题,但是当一个灰色引脚显示typeSelectionView(如上图所示)然后我选择另一个引脚时,就像这部分一样:

if (self.typeSelectionView.superview != annotationView) {
    [self.typeSelectionView removeFromSuperview];
    [self.typeSelectionView showTypeButtons:NO animated:NO completion:NULL];
}

什么也没做。 4个圆圈简单地从一个引脚跳到另一个引脚而没有任何动画。 我期望的是[self.typeSelectionView showTypeButtons:NO animated:NO completion:NULL];将这些按钮设置为“隐藏”(缩放(0,0)并且在引脚的头部中心)没有任何动画(因为隐形视图没有超视图再这样,所以他们甚至没有显示),然后当我用[annotationView addSubview:self.typeSelectionView];将typeSelectionView添加到新的annotationView时,我使用[self.typeSelectionView showTypeButtons:YES animated:YES completion:NULL];再次将圆圈设置为原始位置。

顺便说一下,在[typeButton.layer removeAllAnimations]开头做showTypeButtons:animated:completion:什么也没做。

我该如何解决这个问题?

提前致谢。

编辑:(如果有人可以向我解释这个问题并帮助我解决,可以获奖)=)

假设圆圈如上图所示,那么这段代码:

NSLog(@"type selected");
[self.typeSelectionView showTypeButtons:NO
                               animated:YES
                             completion:^(BOOL finished) {
                                 NSLog(@"finisheddddd: %d", finished);
                             }];

[self.typeSelectionView showTypeButtons:NO
                               animated:YES
                             completion:^(BOOL finished) {
                                 NSLog(@"finished: %d", finished);
                             }];

生成以下输出:

type selected
finished: 1
finisheddddd: 1

所以第二个动画首先结束,两个动画都以finished == YES结束。 第二个动画(首先完成)也会立即结束,而不是在动画结束后结束。

O.o

2 个答案:

答案 0 :(得分:-1)

检查我写的代码但未经过测试。请试用它来获得结果

- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)annotationView
{
if (self.typeSelectionView.superview)
{
    [self.typeSelectionView showTypeButtons:NO
                                   animated:YES
                                 completion:^(BOOL finished) {
                                     if (finished) {
                                         [self.typeSelectionView removeFromSuperview];
                                     }
                                 }];
}
}

 - (void)showTypeButtons:(BOOL)show animated:(BOOL)animated completion:(void (^)  (BOOL))completion
 {

[UIView animateWithDuration:(animated) ?0.5f : 0.0f
                      delay:(self.animationStarted)? 0.5 : 0.0
                    options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^{
                     self.animationStarted = YES;
                     [self setButtonVisible:show];
                 }
                 completion:^(BOOL finished) {
                     self.animationStarted = NO;
                         if (completion) {
                             completion(finished);
                         }
                     }];
}

-(void)setButtonVisible:(BOOL)visible
{
 [self.typeButtons enumerateObjectsUsingBlock:^(TypeButton typeButton, NSUInteger idx, BOOL *stop) {
        if (visible)
         {
             typeButton.center = [self _typeButtonCenterForIndex:idx numberOfButtons:self.typeButtons.count];
             typeButton.transform = CGAffineTransformIdentity;
         }
         else
         {
             typeButton.center = CGPointMake(viewWidth / 2, viewheight + 5); // pin head center
             typeButton.transform = CGAffineTransformMakeScale(0, 0);
         }

 }];
}

答案 1 :(得分:-1)

原来问题是,当我将typeButtons设置为非动画时,它们不会立即重绘,所以它们不会改变它们的当前状态,所以会发生什么:

one mapView:didSelectAnnotationView: method call:
 - show the buttons animated

***redraw cycle here***

another mapView:didSelectAnnotationView: method call:
- hide the buttons non-animated
(no redraw cycle here, so buttons are still showing)
- show the buttons animated

所以我提出了这个糟糕的解决方案:

- (void)showTypeButtons:(BOOL)show animated:(BOOL)animated completion:(void (^)(BOOL))completion
{
    void (^block)(void) = ^{
        for (int i = 0; i < self.typeButtons.count; i++) {
            TypeButton *typeButton = self.typeButtons[i];

            if (show) {
                typeButton.center = [self _typeButtonCenterForIndex:i numberOfButtons:self.typeButtons.count];
                typeButton.transform = CGAffineTransformIdentity;
            } else {
                typeButton.center = CGPointMake(viewWidth / 2, viewheight + 5); // pin head center
                typeButton.transform = CGAffineTransformMakeScale(0, 0);
            }
        }
    };

    if (animated) {
        [UIView animateWithDuration:0.5
                              delay:0
                            options:self.typeButtonsChangedWithoutAnimation ? 0 : UIViewAnimationOptionBeginFromCurrentState
                         animations:block
                         completion:^(BOOL finished) {
                             if (completion) {
                                 completion(finished);
                             }
                         }];
        self.typeButtonsChangedWithoutAnimation = NO;
    } else {
        self.typeButtonsChangedWithoutAnimation = YES;

        block();

        if (completion) {
            completion(YES);
        }
    }
}

如果没有UIViewAnimationOptionBeginFromCurrentState,动画将从其实际状态开始,而不是从其绘制状态开始。

我发现但无效的一个解决方案是:What is the most robust way to force a UIView to redraw? 即使它确实有效,我也不想要它......

是的,我不会接受这个答案,因为它很糟糕。 它实际上并没有解决我的问题,即改变当前状态,而不是通过它。 我只是张贴它以防有人看到并了解如何真正解决我原来的问题。