在viewDidLayoutSubviews中更改框架
首次显示视图控制器的视图时,我想运行一个动画,其中视图控制器中的所有元素都从屏幕底部外部滑动到其自然位置。 为此,我在viewDidLayoutSubviews
执行subview.frame.origin.y += self.view.frame.size.height
。 我也尝试过viewWillAppear
,但它根本不起作用。 然后我使用viewDidAppear
subview.frame.origin.y -= self.view.frame.size.height
将它们设置为自然位置。
问题是viewDidLayoutSubviews
在整个视图控制器的生命周期中被调用了好几次。 因此,当显示键盘的事情发生时,我的所有内容都会再次在视图之外被替换。
有没有更好的方法来做到这一点? 我是否需要添加某种标志来检查动画是否已经运行?
编辑:这是代码。 这里我在viewDidLayoutSubviews
调用prepareAppearance
,它可以工作,但是在整个控制器的生命周期中多次调用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) { }]; } }
如果您需要在显示视图时为某些内容设置动画,然后不再触摸子视图,我建议如下:
- 请勿更改/触摸
viewDidLayoutSubviews
- 在
viewWillAppear
添加逻辑以在屏幕外移动元素(到动画前的初始位置) - 添加逻辑以将元素设置为
viewDidAppear
的正确位置
更新 :
如果你正在使用自动布局(这是非常好的事情),你不能通过直接更改它们的框架来动画视图(因为自动布局会忽略它并再次更改它们)。 您需要做的是将出口暴露给负责Y位置的约束(在您的情况下)并更改约束而不是设置框架。
在动画方法中更新约束后,也不要忘记包含对[weakView layoutIfNeeded]
调用。
我在viewDidAppear:
做了两件事viewDidAppear:
。 似乎当调用viewDidAppear:
时,视图实际上不可见,但即将viewDidAppear:
。 因此,如果在那里替换UI元素,UI元素永远不会显示在其初始位置。