第一次显示 View Controller 的 View 时,我想运行一个动画,其中 View Controller 中的所有元素都从屏幕底部之外滑动到其自然位置。为此,我在subview.frame.origin.y += self.view.frame.size.height中执行viewDidLayoutSubviews。我也尝试过viewWillAppear,但是它根本不起作用。然后,用subview.frame.origin.y -= self.view.frame.size.height中的viewDidAppear将它们设置到自然位置。

问题在于,在 View Controller 的整个生命周期中,多次调用了viewDidLayoutSubviews。这样,当发生诸如显示键盘之类的事情时,我所有的内容都会再次在 View 外部被替换。

有更好的方法吗?我是否需要添加某种标志来检查动画是否已经运行?

编辑:这是代码。在这里,我在prepareAppearance中调用了viewDidLayoutSubviews,它起作用了,但是在 Controller 的整个生命周期中,多次调用了viewDidLayoutSubviews

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [self prepareAppearance];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self animateAppearance];
}


- (NSArray *)animatableViews
{
    return @[self.createAccountButton, self.facebookButton, self.linkedInButton, self.loginButton];
}

- (void)prepareAppearance
{
    NSArray * views = [self animatableViews];
    NSUInteger count = [views count];

    for (NSUInteger it=0 ; it < count ; ++it) {

        UIView * view = [views objectAtIndex:it];
        CGRect frame = view.frame;

        // Move the views outside the screen, to the bottom
        frame.origin.y += self.view.frame.size.height;

        [view setFrame:frame];
    }
}

- (void)animateAppearance
{
    NSArray * views = [self animatableViews];
    NSUInteger count = [views count];

    for (NSUInteger it=0 ; it < count ; ++it) {

        __weak UIView * weakView = [views objectAtIndex:it];
        CGRect referenceFrame = self.view.frame;

        [UIView animateWithDuration:0.4f
                              delay:0.05f * it
                            options:UIViewAnimationOptionCurveEaseOut
                         animations:^{

                             CGRect frame = weakView.frame;
                             frame.origin.y -= referenceFrame.size.height;

                             [weakView setFrame:frame];
                         }
                         completion:^(BOOL finished) {
                         }];
    }
}

最佳答案

如果需要在显示 View 时设置动画,然后在以后不触摸 subview ,则建议以下操作:

  • 请勿更改/触摸viewDidLayoutSubviews
  • 添加逻辑以在viewWillAppear
  • 中将元素移动到屏幕外(动画之前的初始位置)
  • 添加逻辑以使元素动画到viewDidAppear中的适当位置

  • UPDATE :

    如果您使用的是自动布局(这是很好的事情),则无法通过直接更改其框架来为 View 设置动画(因为自动布局会忽略并再次更改它们)。您需要做的是将导出暴露于负责Y位置的约束(在您的情况下),并更改该约束而不是设置框架。

    另外,在更新animation方法中的约束后,请不要忘记包含对[weakView layoutIfNeeded]的调用。

    10-08 15:41