繁体   English   中英

在UIView动画块内调用layoutIfNeeded会导致子视图提前移动

[英]Calling layoutIfNeeded inside UIView animation block cause subviews to move earlier

我正在尝试创建自定义标注气泡。 我有一个动画块设置气泡UIView的比例转换:

self.view.transform = CGAffineTransformMakeScale(0, 0); // (1)
self.view.transform = CGAffineTransformIdentity; // (2)

我要么在(1)中以比例(0,0)开始气泡视图,然后在动画块内以(2)中的Identity动画,或者相反,从(2)到(1)。

如果我没有[self.view layoutIfNeeded]; 在我的动画块中,从(1)到(2)可以正常工作,如下所示:

在此处输入图片说明

但是,当没有[self.view layoutIfNeeded];从(2)返回到(1)时[self.view layoutIfNeeded]; ,子视图会在动画完成前跳到左侧:

在此处输入图片说明

现在,如果我添加[self.view layoutIfNeeded]; 子视图以气泡视图为动画,但是有点延迟:

从(1)到(2):

在此处输入图片说明

或从(2)到(1):

在此处输入图片说明

我已经尝试使用中心约束替换所有顶部和顶部子视图的约束,例如使用自动版式时如何调整CALayer的锚点。 并且还尝试了层变换解决方案(但是这一解决方案打破了布局约束,因为它不能满足所有约束)。

关于如何解决动画问题有什么想法吗?

提前致谢。

更新:我正在用实际调用的方法更新问题

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)annotationView

- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)annotationView

呈现和消除我的自定义标注框(暂时忘记“展开”状态)。

- (void)setCalloutState:(CalloutState)calloutState
               animated:(BOOL)animated
         annotationView:(MKAnnotationView *)annotationView
             completion:(void (^)(BOOL finished))completion
{
    if (self.view.superview == annotationView || !annotationView) {

    } else {
//        [self.view.layer removeAllAnimations];
        [self.view removeFromSuperview];

        self.view.transform = CGAffineTransformIdentity;
        self.view.bounds = CGRectMake(0, 0, normalViewWidth, normalViewHeight);
        self.view.transform = CGAffineTransformMakeScale(0, 0);
        self.view.center = CGPointMake(annotationView.bounds.size.width / 2, 0);

        [annotationView addSubview:self.view];
    }

    void (^animationBlock)(void) = ^{
        self.view.transform = CGAffineTransformIdentity;

        switch (calloutState) {
            case CalloutStateHidden:
                self.view.bounds = CGRectMake(0, 0, normalViewWidth, normalViewHeight);
                self.view.transform = CGAffineTransformMakeScale(0, 0);
                break;
            case CalloutStateNormal:
                self.view.bounds = CGRectMake(0, 0, normalViewWidth, normalViewHeight);
                break;
            case CalloutStateExpanded:
                self.view.bounds = CGRectMake(0, 0, expandedViewWidth, expandedViewHeight);
                break;
            default:
                break;
        }

        self.view.center = CGPointMake(annotationView.bounds.size.width / 2, 0);

        [self.view layoutIfNeeded];
    };

    if (animated) {
        // TODO: figure out why the first animateWithDuration is needed in this nested thing
        [UIView animateWithDuration:0
                              delay:0
                            options:UIViewAnimationOptionBeginFromCurrentState
                         animations:NULL
                         completion:^(BOOL finished) {

                             [UIView animateWithDuration:1.3
                                                   delay:0
                                                 options:UIViewAnimationOptionBeginFromCurrentState
                                              animations:animationBlock
                                              completion:^(BOOL finished) {
                                                  if (finished) {
                                                      self.calloutState = calloutState;

                                                      // TODO: figure out how to end UIView animation instantly so we don't need the second condition at the if
                                                      // having a concurrency problem here
                                                      if (calloutState == CalloutStateHidden && self.view.superview == annotationView) {
                                                          [self.view removeFromSuperview];
                                                      }

                                                      self.editingEnabled = calloutState == CalloutStateExpanded;
                                                  }

                                                  if (completion) {
                                                      completion(finished);
                                                  }
                                              }];

                         }];
        // ---------------------------------------------------------------------------------
    } else {
        animationBlock();

        self.calloutState = calloutState;
        if (calloutState == CalloutStateHidden) {
            [self.view removeFromSuperview];
        }

        self.editingEnabled = calloutState == CalloutStateExpanded;

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

这可能会有所帮助。 根据Apple文档-layoutIfNeeded强制尽早布局

- (void)setNeedsLayout;
- (void)layoutIfNeeded;

因此,您可以尝试setNeedsLayout。 这应该满足您提到的第一种情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM